

<!DOCTYPE html>
<html lang="zh-CN" data-default-color-scheme=auto>



<head>
  <meta charset="UTF-8">
  <link rel="apple-touch-icon" sizes="76x76" href="/img/favicon.png">
  <link rel="icon" href="/img/favicon.png">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, shrink-to-fit=no">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  
  <meta name="theme-color" content="#2f4154">
  <meta name="description" content="
This is OpenCV basic usage.
">
  <meta name="author" content="Veen">
  <meta name="keywords" content="">
  <meta name="description" content="This is OpenCV basic usage.">
<meta property="og:type" content="article">
<meta property="og:title" content="OpenCV Usage">
<meta property="og:url" content="https://veenxz.github.io/yuque/OpenCV%20Usage/index.html">
<meta property="og:site_name" content="Veen">
<meta property="og:description" content="This is OpenCV basic usage.">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2020/png/448115/1603440178301-44b6fa1f-7b79-4f51-9770-fe146abf4862.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_24%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#height=247&amp;id=y2Se2&amp;originHeight=247&amp;originWidth=825&amp;originalType=binary%E2%88%B6=1&amp;size=0&amp;status=done&amp;style=none&amp;width=825">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2020/png/448115/1603440178266-cc0553c7-f38d-48d0-a309-ada3e780d0b3.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_32%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#height=340&amp;id=DKoRJ&amp;originHeight=340&amp;originWidth=1132&amp;originalType=binary%E2%88%B6=1&amp;size=0&amp;status=done&amp;style=none&amp;width=1132">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617367177142-b5027fa2-49d6-47c6-aa07-d82ac4a24636.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_29%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617372204685-7b6fe0d2-2fb1-4ddf-b66f-650223f72d5d.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_12%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617372458921-6db9dcd0-1135-4c92-bd7b-1cbb26db64ed.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_22%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2020/png/448115/1603440178298-913f9e4c-6d5c-43a7-941c-ec6654217258.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_15%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#height=373&amp;id=zbLbG&amp;originHeight=373&amp;originWidth=515&amp;originalType=binary%E2%88%B6=1&amp;size=0&amp;status=done&amp;style=none&amp;width=515">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617372984582-86e680c1-87d3-4230-b2be-68ce9763a4b8.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_20%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617373117773-11493931-ec15-4823-a231-6f286466d6bf.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_19%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2020/png/448115/1603440178303-6873a51b-276b-4905-9624-0a952707553f.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_32%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#height=462&amp;id=UTuXW&amp;originHeight=462&amp;originWidth=1114&amp;originalType=binary%E2%88%B6=1&amp;size=0&amp;status=done&amp;style=none&amp;width=1114">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2020/png/448115/1603440178411-8f454c38-00e2-471f-b55c-a685bd81dce1.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_11%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#height=227&amp;id=GwejM&amp;originHeight=227&amp;originWidth=242&amp;originalType=binary%E2%88%B6=1&amp;size=0&amp;status=done&amp;style=none&amp;width=242">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2020/png/448115/1603440178513-401cc885-25b5-4d3f-9e47-12bb8a41e1de.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_26%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#height=357&amp;id=ZRzWN&amp;originHeight=357&amp;originWidth=903&amp;originalType=binary%E2%88%B6=1&amp;size=0&amp;status=done&amp;style=none&amp;width=903">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2020/png/448115/1603449379350-e2cc40f6-4e82-426c-91c0-1ad4bdf88360.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_16%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2020/png/448115/1603440178758-ce84c7ec-030b-409c-aa06-fbe1075bf145.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_16%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#height=428&amp;id=TMDSZ&amp;originHeight=428&amp;originWidth=544&amp;originalType=binary%E2%88%B6=1&amp;size=0&amp;status=done&amp;style=none&amp;width=544">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2020/png/448115/1603440178744-7d481550-b13d-4807-a893-26484a332d90.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_13%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#height=346&amp;id=PRl0Y&amp;originHeight=346&amp;originWidth=471&amp;originalType=binary%E2%88%B6=1&amp;size=0&amp;status=done&amp;style=none&amp;width=471">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617373330704-bd2a29d0-3b8a-4f2c-8140-17248d3bff23.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_29%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2020/png/448115/1603440178823-96afaa0d-b385-4556-bc9b-0df72a2ff033.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_16%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#height=352&amp;id=pii0x&amp;originHeight=352&amp;originWidth=573&amp;originalType=binary%E2%88%B6=1&amp;size=0&amp;status=done&amp;style=none&amp;width=573">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2020/png/448115/1603440178765-a34f69bf-11b8-4ac1-a264-9e917c835dd1.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_15%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#height=114&amp;id=pU6QE&amp;originHeight=114&amp;originWidth=330&amp;originalType=binary%E2%88%B6=1&amp;size=0&amp;status=done&amp;style=none&amp;width=330">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2020/png/448115/1603440178759-f415d73a-be00-49f5-8331-30fc25003d01.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_13%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#height=85&amp;id=UCeET&amp;originHeight=85&amp;originWidth=296&amp;originalType=binary%E2%88%B6=1&amp;size=0&amp;status=done&amp;style=none&amp;width=296">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2020/png/448115/1603440178760-e43ede53-fd59-4244-bc2a-536c394482b9.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_9%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#height=64&amp;id=zf3dA&amp;originHeight=64&amp;originWidth=209&amp;originalType=binary%E2%88%B6=1&amp;size=0&amp;status=done&amp;style=none&amp;width=209">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2020/png/448115/1603440178720-f53e78b9-3241-45ad-b4f0-ebc840a4b696.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_9%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#height=63&amp;id=YtGQ9&amp;originHeight=63&amp;originWidth=159&amp;originalType=binary%E2%88%B6=1&amp;size=0&amp;status=done&amp;style=none&amp;width=159">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2020/png/448115/1603440178814-da807751-1cb6-4f96-968f-a195d73c1a34.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_12%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#height=102&amp;id=yWjN7&amp;originHeight=102&amp;originWidth=432&amp;originalType=binary%E2%88%B6=1&amp;size=0&amp;status=done&amp;style=none&amp;width=432">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617373487855-b1437839-ef57-4731-a063-f1898447b55a.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_20%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2020/png/448115/1603440178832-6c6e20b7-9366-426b-87a7-8e1fe5917a66.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_12%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#height=124&amp;id=HLuiw&amp;originHeight=124&amp;originWidth=409&amp;originalType=binary%E2%88%B6=1&amp;size=0&amp;status=done&amp;style=none&amp;width=409">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2020/png/448115/1603440178751-bd7a8973-d495-4146-b0ac-e68ea9a54113.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_10%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#height=73&amp;id=ZikP8&amp;originHeight=73&amp;originWidth=214&amp;originalType=binary%E2%88%B6=1&amp;size=0&amp;status=done&amp;style=none&amp;width=214">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2020/png/448115/1603440178794-884b148f-b8c3-4278-9471-917b9258aa48.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_12%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#height=146&amp;id=P6cFP&amp;originHeight=146&amp;originWidth=405&amp;originalType=binary%E2%88%B6=1&amp;size=0&amp;status=done&amp;style=none&amp;width=405">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617373576429-c1a9326c-56f3-4ab4-9dcb-e0f37e1e18b5.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_21%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617373620628-4ba09de1-c440-4899-a033-84c9de766402.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_23%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2020/png/448115/1603448225125-72b2c7aa-30e9-4b45-985e-8dd593ce62f7.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_27%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617374948515-3a42045d-2d3c-4401-b092-0d602caeab02.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_20%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617374931837-0282dca4-6743-42cd-9d00-b0ad2bacbfa3.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_21%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#height=274&amp;id=M9MMf&amp;margin=%5Bobject%20Object%5D&amp;name=image.png&amp;originHeight=274&amp;originWidth=720&amp;originalType=binary%E2%88%B6=1&amp;size=32674&amp;status=done&amp;style=none&amp;width=720">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617374915472-40958e3a-1812-4d57-be20-e0a1a5ddd6e7.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_23%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617374906407-98a10cac-cee2-458e-baf9-896895dd8513.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_21%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#height=467&amp;id=s3InA&amp;margin=%5Bobject%20Object%5D&amp;name=image.png&amp;originHeight=467&amp;originWidth=729&amp;originalType=binary%E2%88%B6=1&amp;size=86120&amp;status=done&amp;style=none&amp;width=729">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617374899714-983e6827-bf2d-4886-bfa6-402832bc82f2.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_21%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617374873761-0ab46f02-d306-42b9-bf8e-10dca2cacf6b.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_21%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617374862119-8c27ef5b-4be8-43e7-881d-f960797865d1.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_21%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#height=36&amp;id=ee0ev&amp;margin=%5Bobject%20Object%5D&amp;name=image.png&amp;originHeight=36&amp;originWidth=730&amp;originalType=binary%E2%88%B6=1&amp;size=41420&amp;status=done&amp;style=none&amp;width=730">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617374855658-b2d047d0-6088-4243-a786-795b65057c72.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_21%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#height=50&amp;id=wWv6n&amp;margin=%5Bobject%20Object%5D&amp;name=image.png&amp;originHeight=50&amp;originWidth=747&amp;originalType=binary%E2%88%B6=1&amp;size=20646&amp;status=done&amp;style=none&amp;width=747">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617374834506-499ee6d6-d554-46f3-bf3d-1eebc4068026.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_20%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617374789561-e36f7d13-78bf-41f2-846a-0d488cef9e57.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_23%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617375885885-a3d85457-7f4e-4b67-8a51-4016343be0f7.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_22%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617376001833-af45b947-9eda-49ed-8e1f-34938b838c78.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_9%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#height=65&amp;id=Zacjr&amp;margin=%5Bobject%20Object%5D&amp;name=image.png&amp;originHeight=65&amp;originWidth=208&amp;originalType=binary%E2%88%B6=1&amp;size=3151&amp;status=done&amp;style=none&amp;width=208">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617375856318-5b0be950-77ac-4cb4-b0c7-d5981ab2d778.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_16%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617375865502-4420295d-1876-4855-998c-98596085cef8.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_23%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/svg/448115/1617375239079-004d5d20-619a-4893-bb42-8e3f513abca0.svg#height=26&amp;id=GcbqM&amp;originHeight=26&amp;originWidth=31&amp;originalType=binary%E2%88%B6=1&amp;size=0&amp;status=done&amp;style=none&amp;width=31">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617375835493-94ba0dd4-a6e1-43cf-83dc-09f0b10cd6bb.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_12%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617375820770-d5964ba2-00d1-48b8-863e-fab2c4854d05.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_9%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617375798284-c005a796-bb2c-4b64-90fa-4cccfc2ee003.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_22%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617375765245-e97fa825-af21-4637-86b7-b7833ff0e995.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_15%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617375759114-424b7cbc-8a3c-42d5-9232-b52dd5f3ee3f.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_23%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617375781101-2fbabbde-1b74-49d2-856d-758c1ecaccc0.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_16%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617375744756-b50fc8d4-5513-417b-b2a3-2a18a805d8b2.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_18%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617375738852-f263a075-8271-49e8-8e06-1bd47c47ad89.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_20%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617375732376-43bc0848-899c-422b-a097-7a9bfafa7192.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_19%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617375726494-39383d76-8885-464e-8561-53b8f55ec4ef.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_18%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617375718904-05fd2bea-e5e1-4b24-8bcb-3a8f7d7fd134.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_22%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617375713230-8843b8e8-9c1b-4018-998a-8c3e2a77a3cf.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_18%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617375680991-576a8ace-4523-47d0-99df-3313eb0f70a8.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_22%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617375247382-9f988e06-7bfe-4f82-9d0a-44949f150a31.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_23%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617376678723-d8fe5595-5f70-484e-8b18-c8d9a5d6e116.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_23%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617376693608-91a9c642-5b14-49e3-9b6e-2fd1047fdacb.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_11%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617376668953-01dcb858-4e87-4397-882a-28633f90e357.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_22%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617376635328-6a2c57fb-e225-4813-9f30-fffd7caed102.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_22%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617376623443-6efa5f2c-24a5-4f69-9670-262f67cf5bb0.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_22%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617376615886-e5725fde-fc20-47e8-b547-ea602bbadade.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_12%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617376577195-52b44c01-6629-4c05-962e-02d45e50232f.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_22%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617376570455-7142ab38-c36c-4b4b-aeaa-d21ef094c538.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_23%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617376564263-1403744a-7809-4bd2-8d72-a2192772f7e0.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_22%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617376557497-b765bbed-92ea-4484-99ef-b1a7d8434eb0.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_22%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617377190404-c2a71ea9-27b3-4799-aba5-823d631a7e59.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_23%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617377178784-2f2a9212-74cc-4651-997d-ada83b56e57f.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_21%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#height=209&amp;id=TKn3a&amp;margin=%5Bobject%20Object%5D&amp;name=image.png&amp;originHeight=279&amp;originWidth=738&amp;originalType=binary%E2%88%B6=1&amp;size=179409&amp;status=done&amp;style=none&amp;width=554">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617377171251-7516ea06-812d-4a24-8a3a-21f2e5c845ff.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_18%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#height=335&amp;id=X22A8&amp;margin=%5Bobject%20Object%5D&amp;name=image.png&amp;originHeight=447&amp;originWidth=620&amp;originalType=binary%E2%88%B6=1&amp;size=127141&amp;status=done&amp;style=none&amp;width=465">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617377164280-c85606e8-79fb-47b9-b006-e3e9b8a4c077.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_11%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617377156190-28c86fd2-22ed-4222-afa5-6994e3381cdd.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_11%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617377133476-ee259707-0799-4c31-acb2-18082604c5dc.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_13%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617377114292-a35d555e-6463-41f4-877e-d6acb774b34f.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_11%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617377098548-d1bd10e9-df5c-475e-9da1-17dbbe0fd576.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_11%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617377084686-0be8d4b5-eb61-4787-bff9-d2085b730b9a.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_9%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617377073536-78f87609-40c3-4c42-8332-dc9159c41ac4.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_12%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617377034799-83b2e7a5-ef7a-4439-8094-ef9db3e81348.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_22%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617377022361-4ec9ad73-a7a5-4ab2-a779-7c668b5596bf.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_22%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617377016331-be2787d2-aa58-49ce-9dc0-2c99a91c9b94.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_9%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617376999678-19e56a4d-05f8-4c5b-bf8b-86803e956508.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_15%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617376988035-b58adb27-37cd-447e-a4bd-fa7ffacc8a51.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_9%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617376952463-e93b42ef-dbe2-47aa-92c9-3bc78bcc64e9.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_22%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617376937104-e4869760-be44-41f0-aac1-fd6550fd872a.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_14%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617376919582-7251825c-727f-477b-b029-eeed0cad0cb1.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_18%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617376911750-bf045179-b69d-4414-ad16-ec8c3e9d1940.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_17%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617376885925-6f7de64d-2e84-49d4-9b47-bac864590aff.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_22%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617377677931-6e3c17cf-26c5-4156-a6b0-b819e68aa492.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_12%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#height=149&amp;id=IFkQw&amp;margin=%5Bobject%20Object%5D&amp;name=image.png&amp;originHeight=149&amp;originWidth=422&amp;originalType=binary%E2%88%B6=1&amp;size=150362&amp;status=done&amp;style=none&amp;width=422">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617377673251-4f53ff68-42ab-4e1b-a070-ed608a3e7476.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_14%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617377667733-aa5a1cb9-e1f2-4b3d-8db6-a86c2a4c952c.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_14%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617377637806-0d0ce97a-04d1-4012-b564-d677da0f4e9d.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_16%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617377632803-a9d606a9-0035-4d08-8ee9-b0dc630300eb.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_9%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617377621291-350eab8c-3516-45a7-8001-733004b201e4.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_19%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617377611899-bfd17796-4839-4f21-82de-f28bab27aff3.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_22%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617377535308-7771b36c-d3dc-4cfc-94d4-18de2b68287d.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_21%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617377528808-ae67a32f-4daf-47e9-ac08-fbadc061a003.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_15%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617377847178-1e513072-e10b-4e7a-abb1-11fbd68ed1cd.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_20%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617377489138-a6315a35-5c2e-47db-8a3e-6cc76a530795.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_10%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617377436506-2c5f0412-f673-47ec-9648-ba6b65b2383c.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_21%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617378066912-406b06cc-fbac-4afd-8bdb-ef88de756e78.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_20%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617378222014-ef2ddd85-a472-4d8f-bac1-ed9bfed8aff7.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_13%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617378507131-8a1f983c-1458-451b-8692-dc52ee0e1748.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_13%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/gif/448115/1617378497427-d75bfef1-ef0a-4ae0-a1cd-5d5384e25270.gif#height=283&amp;id=ZkoqE&amp;margin=%5Bobject%20Object%5D&amp;name=image2-0785334.gif&amp;originHeight=283&amp;originWidth=212&amp;originalType=binary%E2%88%B6=1&amp;size=180533&amp;status=done&amp;style=none&amp;width=212">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/png/448115/1617378449987-8566d6e0-96f1-40c4-9ec0-e5bebea8a60d.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_22%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10">
<meta property="og:image" content="https://cdn.nlark.com/yuque/0/2021/gif/448115/1617378432441-480ada39-1949-42f4-abf3-6fc6561f96b5.gif#height=510&amp;id=okHSy&amp;margin=%5Bobject%20Object%5D&amp;name=image4.gif&amp;originHeight=510&amp;originWidth=340&amp;originalType=binary%E2%88%B6=1&amp;size=253144&amp;status=done&amp;style=none&amp;width=340">
<meta property="article:published_time" content="2021-10-17T13:51:14.000Z">
<meta property="article:modified_time" content="2021-10-27T13:18:05.176Z">
<meta property="article:author" content="Veen">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:image" content="https://cdn.nlark.com/yuque/0/2020/png/448115/1603440178301-44b6fa1f-7b79-4f51-9770-fe146abf4862.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_24%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#height=247&amp;id=y2Se2&amp;originHeight=247&amp;originWidth=825&amp;originalType=binary%E2%88%B6=1&amp;size=0&amp;status=done&amp;style=none&amp;width=825">
  
  <title>OpenCV Usage - Veen</title>

  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4/dist/css/bootstrap.min.css" />


  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/github-markdown-css@4/github-markdown.min.css" />
  <link  rel="stylesheet" href="/lib/hint/hint.min.css" />

  
    
    
      
      
        
          
        
        <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/prismjs@1/themes/prism.min.css" />
      
      
        <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/prismjs@1/plugins/line-numbers/prism-line-numbers.min.css" />
      
    
  

  
    <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3/dist/jquery.fancybox.min.css" />
  


<!-- 主题依赖的图标库，不要自行修改 -->

<link rel="stylesheet" href="//at.alicdn.com/t/font_1749284_ba1fz6golrf.css">



<link rel="stylesheet" href="//at.alicdn.com/t/font_1736178_kmeydafke9r.css">


<link  rel="stylesheet" href="/css/main.css" />

<!-- 自定义样式保持在最底部 -->


  <script id="fluid-configs">
    var Fluid = window.Fluid || {};
    var CONFIG = {"hostname":"veenxz.github.io","root":"/","version":"1.8.12","typing":{"enable":true,"typeSpeed":70,"cursorChar":"_","loop":false},"anchorjs":{"enable":true,"element":"h1,h2,h3,h4,h5,h6","placement":"right","visible":"hover","icon":""},"progressbar":{"enable":true,"height_px":3,"color":"#29d","options":{"showSpinner":false,"trickleSpeed":100}},"copy_btn":true,"image_zoom":{"enable":true,"img_url_replace":["",""]},"toc":{"enable":true,"headingSelector":"h1,h2,h3,h4,h5,h6","collapseDepth":0},"lazyload":{"enable":true,"loading_img":"/img/loading.gif","onlypost":false,"offset_factor":2},"web_analytics":{"enable":false,"baidu":null,"google":null,"gtag":null,"tencent":{"sid":null,"cid":null},"woyaola":null,"cnzz":null,"leancloud":{"app_id":null,"app_key":null,"server_url":null,"path":"window.location.pathname"}},"search_path":"/local-search.xml"};
  </script>
  <script  src="/js/utils.js" ></script>
  <script  src="/js/color-schema.js" ></script>
<meta name="generator" content="Hexo 6.3.0"></head>


<body>
  <header style="height: 55vh;">
    <nav id="navbar" class="navbar fixed-top  navbar-expand-lg navbar-dark scrolling-navbar">
  <div class="container">
    <a class="navbar-brand" href="/">
      <strong>Veen</strong>
    </a>

    <button id="navbar-toggler-btn" class="navbar-toggler" type="button" data-toggle="collapse"
            data-target="#navbarSupportedContent"
            aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <div class="animated-icon"><span></span><span></span><span></span></div>
    </button>

    <!-- Collapsible content -->
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav ml-auto text-center">
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/">
                <i class="iconfont icon-home-fill"></i>
                首页
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/archives/">
                <i class="iconfont icon-archive-fill"></i>
                归档
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/categories/">
                <i class="iconfont icon-category-fill"></i>
                分类
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/tags/">
                <i class="iconfont icon-tags-fill"></i>
                标签
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/about/">
                <i class="iconfont icon-user-fill"></i>
                关于
              </a>
            </li>
          
        
        
          <li class="nav-item" id="search-btn">
            <a class="nav-link" target="_self" href="javascript:;" data-toggle="modal" data-target="#modalSearch" aria-label="Search">
              &nbsp;<i class="iconfont icon-search"></i>&nbsp;
            </a>
          </li>
        
        
          <li class="nav-item" id="color-toggle-btn">
            <a class="nav-link" target="_self" href="javascript:;" aria-label="Color Toggle">&nbsp;<i
                class="iconfont icon-dark" id="color-toggle-icon"></i>&nbsp;</a>
          </li>
        
      </ul>
    </div>
  </div>
</nav>

    <div class="banner" id="banner" parallax=true
         style="background: url('/img/cinque-terre.jpg') no-repeat center center;
           background-size: cover;">
      <div class="full-bg-img">
        <div class="mask flex-center" style="background-color: rgba(0, 0, 0, 0.3)">
          <div class="page-header text-center fade-in-up">
            <span class="h2" id="subtitle" title="OpenCV Usage">
              
            </span>

            
              <div class="mt-3">
  
  
    <span class="post-meta">
      <i class="iconfont icon-date-fill" aria-hidden="true"></i>
      <time datetime="2021-10-17 21:51" pubdate>
        2021年10月17日 晚上
      </time>
    </span>
  
</div>

<div class="mt-1">
  
    <span class="post-meta mr-2">
      <i class="iconfont icon-chart"></i>
      41k 字
    </span>
  

  
    <span class="post-meta mr-2">
      <i class="iconfont icon-clock-fill"></i>
      
      
      128 分钟
    </span>
  

  
  
</div>

            
          </div>

          
        </div>
      </div>
    </div>
  </header>

  <main>
    
      

<div class="container-fluid nopadding-x">
  <div class="row nomargin-x">
    <div class="d-none d-lg-block col-lg-2"></div>
    <div class="col-lg-8 nopadding-x-md">
      <div class="container nopadding-x-md" id="board-ctn">
        <div class="py-5" id="board">
          <article class="post-content mx-auto">
            <!-- SEO header -->
            <h1 style="display: none">OpenCV Usage</h1>
            
              <p class="note note-info">
                
                  本文最后更新于：2021年10月27日 晚上
                
              </p>
            
            <div class="markdown-body">
              <blockquote>
<p>This is OpenCV basic usage.</p>
</blockquote>
<span id="more"></span>
<p>​</p>
<p>OpenCV 是一款由 Intel 公司俄罗斯团队发起并参与和维护的一个计算机视觉处理开源软件库，支持与计算机视觉和机器学习相关的众多算法。</p>
<h2 id="1-opencv-包安装"><a href="#1-opencv-包安装" class="headerlink" title="1. opencv 包安装"></a>1. opencv 包安装</h2><div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python">pip install opencv<span class="token operator">-</span>contrib<span class="token operator">-</span>python <span class="token operator">-</span>i https<span class="token punctuation">:</span><span class="token operator">//</span>mirrors<span class="token punctuation">.</span>aliyun<span class="token punctuation">.</span>com<span class="token operator">/</span>pypi<span class="token operator">/</span>simple<span class="token operator">/</span><span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre></div>
<p>官方文档：<a target="_blank" rel="noopener" href="https://opencv-python-tutroals.readthedocs.io/en/latest/">https://opencv-python-tutroals.readthedocs.io/en/latest/</a></p>
<h2 id="2-opencv-简单图像处理"><a href="#2-opencv-简单图像处理" class="headerlink" title="2. opencv 简单图像处理"></a>2. opencv 简单图像处理</h2><h3 id="2-1-图像像素存储形式"><a href="#2-1-图像像素存储形式" class="headerlink" title="2.1 图像像素存储形式"></a>2.1 图像像素存储形式</h3><p>首先得了解下图像在计算机中存储形式：(为了方便画图，每列像素值都写一样了)<br>对于只有黑白颜色的灰度图，为单通道，一个像素块对应矩阵中一个数字，数值为 0 到 255, 其中 0 表示最暗（黑色） ，255 表示最亮（白色）<br>　　　　<img src="https://cdn.nlark.com/yuque/0/2020/png/448115/1603440178301-44b6fa1f-7b79-4f51-9770-fe146abf4862.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_24%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#height=247&amp;id=y2Se2&amp;originHeight=247&amp;originWidth=825&amp;originalType=binary∶=1&amp;size=0&amp;status=done&amp;style=none&amp;width=825" srcset="/img/loading.gif" lazyload alt=""></p>
<p>对于采用 RGB 模式的彩色图片，为三通道图，Red、Green、Blue 三原色，按不同比例相加，一个像素块对应矩阵中的一个向量, 如[24,180, 50]，分别表示三种颜色的比列, 即对应深度上的数字，如下图所示：<br>　　　　<img src="https://cdn.nlark.com/yuque/0/2020/png/448115/1603440178266-cc0553c7-f38d-48d0-a309-ada3e780d0b3.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_32%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#height=340&amp;id=DKoRJ&amp;originHeight=340&amp;originWidth=1132&amp;originalType=binary∶=1&amp;size=0&amp;status=done&amp;style=none&amp;width=1132" srcset="/img/loading.gif" lazyload alt=""><br><strong>注意：</strong>由于历史遗留问题，opencv 采用 BGR 模式，而不是 RGB</p>
<h3 id="2-2-图像读取和写入"><a href="#2-2-图像读取和写入" class="headerlink" title="2.2 图像读取和写入"></a>2.2 图像读取和写入</h3><p><strong>cv.imread()</strong></p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python">cv<span class="token punctuation">.</span>imread<span class="token punctuation">(</span>img_path<span class="token punctuation">,</span> flag<span class="token punctuation">)</span> 读取图片，返回图片对象
    img_path<span class="token punctuation">:</span> 图片的路径，即使路径错误也不会报错，但打印返回的图片对象为<span class="token boolean">None</span>
    flag：cv<span class="token punctuation">.</span>IMREAD_COLOR，读取彩色图片，图片透明性会被忽略，为默认参数，也可以传入<span class="token number">1</span>
          cv<span class="token punctuation">.</span>IMREAD_GRAYSCALE<span class="token punctuation">,</span>按灰度模式读取图像，也可以传入<span class="token number">0</span>
          cv<span class="token punctuation">.</span>IMREAD_UNCHANGED<span class="token punctuation">,</span>读取图像，包括其alpha通道，也可以传入<span class="token operator">-</span><span class="token number">1</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p><strong>cv.imshow()</strong></p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python">cv<span class="token punctuation">.</span>imshow<span class="token punctuation">(</span>window_name<span class="token punctuation">,</span> img<span class="token punctuation">)</span>：显示图片，窗口自适应图片大小
    window_name<span class="token punctuation">:</span> 指定窗口的名字
    img：显示的图片对象
    可以指定多个窗口名称，显示多个图片

cv<span class="token punctuation">.</span>waitKey<span class="token punctuation">(</span>millseconds<span class="token punctuation">)</span>  键盘绑定事件，阻塞监听键盘按键，返回一个数字（不同按键对应的数字不同）
    millseconds<span class="token punctuation">:</span> 传入时间毫秒数，在该时间内等待键盘事件；传入<span class="token number">0</span>时，会一直等待键盘事件

cv<span class="token punctuation">.</span>destroyAllWindows<span class="token punctuation">(</span>window_name<span class="token punctuation">)</span>
    window_name<span class="token punctuation">:</span> 需要销毁的窗口名字，不传入时关闭所有窗口<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p><strong>cv.imwrite()</strong></p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python">cv<span class="token punctuation">.</span>imwrite<span class="token punctuation">(</span>img_path_name<span class="token punctuation">,</span> img<span class="token punctuation">)</span>
    img_path_name<span class="token punctuation">:</span>保存的文件名
    img：文件对象<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code></pre></div>
<p><strong>cv.cvtColor()</strong></p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python">cv<span class="token punctuation">.</span>cvtColor<span class="token punctuation">(</span><span class="token punctuation">)</span>
    参数：
        img<span class="token punctuation">:</span> 图像对象
        code：
            cv<span class="token punctuation">.</span>COLOR_RGB2GRAY<span class="token punctuation">:</span> RGB转换到灰度模式
            cv<span class="token punctuation">.</span>COLOR_RGB2HSV： RGB转换到HSV模式（hue<span class="token punctuation">,</span>saturation<span class="token punctuation">,</span>Value）
cv<span class="token punctuation">.</span>inRange<span class="token punctuation">(</span><span class="token punctuation">)</span>
    参数：
        img<span class="token punctuation">:</span> 图像对象<span class="token operator">/</span>array
        lowerb<span class="token punctuation">:</span> 低边界array，  如lower_blue <span class="token operator">=</span> np<span class="token punctuation">.</span>array<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token number">110</span><span class="token punctuation">,</span><span class="token number">50</span><span class="token punctuation">,</span><span class="token number">50</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
        upperb：高边界array， 如 upper_blue <span class="token operator">=</span> np<span class="token punctuation">.</span>array<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token number">130</span><span class="token punctuation">,</span><span class="token number">255</span><span class="token punctuation">,</span><span class="token number">255</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
    mask <span class="token operator">=</span> cv<span class="token punctuation">.</span>inRange<span class="token punctuation">(</span>hsv<span class="token punctuation">,</span> lower_green<span class="token punctuation">,</span> upper_green<span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p>使用示例：</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token keyword">import</span> cv2 <span class="token keyword">as</span> av

img <span class="token operator">=</span> cv<span class="token punctuation">.</span>imread<span class="token punctuation">(</span><span class="token string">r"./image/kids.jpg"</span><span class="token punctuation">)</span>
<span class="token comment"># print(img.shape)</span>
<span class="token comment"># 将图片灰度处理</span>
img_gray <span class="token operator">=</span> cv<span class="token punctuation">.</span>cvtColor<span class="token punctuation">(</span>img<span class="token punctuation">,</span> cv<span class="token punctuation">.</span>COLOR_BGR2GRAY<span class="token punctuation">)</span>
ret<span class="token punctuation">,</span> img_threshold <span class="token operator">=</span> cv<span class="token punctuation">.</span>threshold<span class="token punctuation">(</span>img_gray<span class="token punctuation">,</span> <span class="token number">127</span><span class="token punctuation">,</span> <span class="token number">255</span><span class="token punctuation">,</span> cv<span class="token punctuation">.</span>THRESH_BINARY<span class="token punctuation">)</span>
cv<span class="token punctuation">.</span>imshow<span class="token punctuation">(</span><span class="token string">"img"</span><span class="token punctuation">,</span> img<span class="token punctuation">)</span>
cv<span class="token punctuation">.</span>imshow<span class="token punctuation">(</span><span class="token string">"thre"</span><span class="token punctuation">,</span> img_threshold<span class="token punctuation">)</span>
key <span class="token operator">=</span> cv<span class="token punctuation">.</span>waitKey<span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span>
cv<span class="token punctuation">.</span>imwrite<span class="token punctuation">(</span><span class="token string">r"./image/kids1.jpg"</span><span class="token punctuation">,</span> img_threshold<span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617367177142-b5027fa2-49d6-47c6-aa07-d82ac4a24636.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_29%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png"></p>
<h3 id="2-3-绘制图形和文字"><a href="#2-3-绘制图形和文字" class="headerlink" title="2.3 绘制图形和文字"></a>2.3 绘制图形和文字</h3><p><strong>绘制图形</strong></p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token comment"># 绘制直线</span>
cv<span class="token punctuation">.</span>line<span class="token punctuation">(</span>img<span class="token punctuation">,</span> start<span class="token punctuation">,</span> end<span class="token punctuation">,</span> color<span class="token punctuation">,</span> thickness<span class="token punctuation">)</span>
    img<span class="token punctuation">:</span>要绘制直线的图像
    Start<span class="token punctuation">,</span>end<span class="token punctuation">:</span> 直线的起点和终点
    color<span class="token punctuation">:</span> 线条的颜色
    Thickness<span class="token punctuation">:</span> 线条宽度

<span class="token comment"># 绘制圆形</span>
cv<span class="token punctuation">.</span>circle<span class="token punctuation">(</span>img<span class="token punctuation">,</span> centerpoint<span class="token punctuation">,</span> r<span class="token punctuation">,</span> color<span class="token punctuation">,</span> thickness<span class="token punctuation">)</span>
    mg<span class="token punctuation">:</span>要绘制圆形的图像
    Centerpoint<span class="token punctuation">,</span> r<span class="token punctuation">:</span> 圆心和半径
    color<span class="token punctuation">:</span> 线条的颜色
    Thickness<span class="token punctuation">:</span> 线条宽度，为<span class="token operator">-</span><span class="token number">1</span>时生成闭合图案并填充颜色

<span class="token comment"># 绘制矩形</span>
cv<span class="token punctuation">.</span>rectangle<span class="token punctuation">(</span>img<span class="token punctuation">,</span>leftupper<span class="token punctuation">,</span>rightdown<span class="token punctuation">,</span>color<span class="token punctuation">,</span>thickness<span class="token punctuation">)</span>
    img<span class="token punctuation">:</span>要绘制矩形的图像
    Leftupper<span class="token punctuation">,</span> rightdown<span class="token punctuation">:</span> 矩形的左上角和右下角坐标
    color<span class="token punctuation">:</span> 线条的颜色
    Thickness<span class="token punctuation">:</span> 线条宽度<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p><strong>向图像中添加文字</strong></p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token comment"># 向图像中添加文字</span>
cv<span class="token punctuation">.</span>putText<span class="token punctuation">(</span>img<span class="token punctuation">,</span> text<span class="token punctuation">,</span> station<span class="token punctuation">,</span> font<span class="token punctuation">,</span> fontsize<span class="token punctuation">,</span> color<span class="token punctuation">,</span> thickness<span class="token punctuation">,</span> cv<span class="token punctuation">.</span>LINE_AA<span class="token punctuation">)</span>
    img<span class="token punctuation">:</span> 图像
    text：要写入的文本数据
    station：文本的放置位置
    font：字体
    Fontsize <span class="token punctuation">:</span>字体大小<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p>使用示例：</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token keyword">import</span> numpy <span class="token keyword">as</span> np
<span class="token keyword">import</span> cv2 <span class="token keyword">as</span> cv
<span class="token keyword">import</span> matplotlib<span class="token punctuation">.</span>pyplot <span class="token keyword">as</span> plt

<span class="token comment"># 1 创建一个空白的图像</span>
img <span class="token operator">=</span> np<span class="token punctuation">.</span>zeros<span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token number">512</span><span class="token punctuation">,</span> <span class="token number">512</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">,</span> np<span class="token punctuation">.</span>uint8<span class="token punctuation">)</span>
<span class="token comment"># 2 绘制图形</span>
cv<span class="token punctuation">.</span>line<span class="token punctuation">(</span>img<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token number">511</span><span class="token punctuation">,</span> <span class="token number">511</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token number">255</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">)</span>
cv<span class="token punctuation">.</span>rectangle<span class="token punctuation">(</span>img<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token number">384</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token number">510</span><span class="token punctuation">,</span> <span class="token number">128</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">255</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">)</span>
cv<span class="token punctuation">.</span>circle<span class="token punctuation">(</span>img<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token number">447</span><span class="token punctuation">,</span> <span class="token number">63</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token number">63</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">255</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span>
font <span class="token operator">=</span> cv<span class="token punctuation">.</span>FONT_HERSHEY_SIMPLEX
cv<span class="token punctuation">.</span>putText<span class="token punctuation">(</span>img<span class="token punctuation">,</span> <span class="token string">'OpenCV'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">,</span> <span class="token number">500</span><span class="token punctuation">)</span><span class="token punctuation">,</span> font<span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token number">255</span><span class="token punctuation">,</span> <span class="token number">255</span><span class="token punctuation">,</span> <span class="token number">255</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> cv<span class="token punctuation">.</span>LINE_AA<span class="token punctuation">)</span>
<span class="token comment"># 3 图像展示</span>
plt<span class="token punctuation">.</span>imshow<span class="token punctuation">(</span>img<span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>title<span class="token punctuation">(</span><span class="token string">'匹配结果'</span><span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>xticks<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>yticks<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>show<span class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617372204685-7b6fe0d2-2fb1-4ddf-b66f-650223f72d5d.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_12%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png"></p>
<h3 id="2-4-图像像素获取和裁剪"><a href="#2-4-图像像素获取和裁剪" class="headerlink" title="2.4 图像像素获取和裁剪"></a>2.4 图像像素获取和裁剪</h3><p><strong>获取并修改图像中的像素点</strong></p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token keyword">import</span> numpy <span class="token keyword">as</span> np
<span class="token keyword">import</span> cv2 <span class="token keyword">as</span> cv

img <span class="token operator">=</span> cv<span class="token punctuation">.</span>imread<span class="token punctuation">(</span><span class="token string">'./image/kids.jpg'</span><span class="token punctuation">)</span>
<span class="token comment"># 获取某个像素点的值</span>
px <span class="token operator">=</span> img<span class="token punctuation">[</span><span class="token number">100</span><span class="token punctuation">,</span> <span class="token number">100</span><span class="token punctuation">]</span>
<span class="token keyword">print</span><span class="token punctuation">(</span>px<span class="token punctuation">)</span>
<span class="token comment"># 仅获取蓝色通道的强度值</span>
blue <span class="token operator">=</span> img<span class="token punctuation">[</span><span class="token number">100</span><span class="token punctuation">,</span> <span class="token number">100</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">]</span>
<span class="token keyword">print</span><span class="token punctuation">(</span>blue<span class="token punctuation">)</span>
<span class="token comment"># 修改某个位置的像素值</span>
img<span class="token punctuation">[</span><span class="token number">100</span><span class="token punctuation">,</span> <span class="token number">100</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">255</span><span class="token punctuation">,</span> <span class="token number">255</span><span class="token punctuation">,</span> <span class="token number">255</span><span class="token punctuation">]</span>

<span class="token punctuation">[</span><span class="token number">142</span> <span class="token number">187</span> <span class="token number">190</span><span class="token punctuation">]</span>
<span class="token number">142</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p><strong>图片性质</strong><br>图像属性包括行数，列数和通道数，图像数据类型，像素数等。<br><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617372458921-6db9dcd0-1135-4c92-bd7b-1cbb26db64ed.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_22%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png"><br><div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token keyword">import</span> cv2 <span class="token keyword">as</span> cv
img <span class="token operator">=</span> cv<span class="token punctuation">.</span>imread<span class="token punctuation">(</span><span class="token string">r"./image/kids.jpg"</span><span class="token punctuation">)</span>

<span class="token comment"># rows, cols, channels</span>
img<span class="token punctuation">.</span>shape   <span class="token comment">#返回(280, 450, 3), 宽280(rows)，长450(cols)，3通道(channels)</span>
<span class="token comment"># size</span>
img<span class="token punctuation">.</span>size    <span class="token comment">#返回378000，所有像素数量，=280*450*3</span>
<span class="token comment"># type</span>
img<span class="token punctuation">.</span>dtype   <span class="token comment">#dtype('uint8')</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div></p>
<p><strong>ROI 截取（Range of Interest）</strong><br>有时需要在 B，G，R 通道图像上单独工作。在这种情况下，需要将 BGR 图像分割为单个通道。或者在其他情况下，可能需要将这些单独的通道合并到 BGR 图像。你可以通过以下方式完成。</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token comment">#ROI,Range of instrest</span>
roi <span class="token operator">=</span> img<span class="token punctuation">[</span><span class="token number">100</span><span class="token punctuation">:</span><span class="token number">200</span><span class="token punctuation">,</span><span class="token number">300</span><span class="token punctuation">:</span><span class="token number">400</span><span class="token punctuation">]</span>  <span class="token comment">#截取100行到200行，列为300到400列的整块区域</span>
img<span class="token punctuation">[</span><span class="token number">50</span><span class="token punctuation">:</span><span class="token number">150</span><span class="token punctuation">,</span><span class="token number">200</span><span class="token punctuation">:</span><span class="token number">300</span><span class="token punctuation">]</span> <span class="token operator">=</span> roi   <span class="token comment">#将截取的roi移动到该区域 （50到100行，200到300列）</span>
b <span class="token operator">=</span> img<span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token punctuation">,</span><span class="token punctuation">:</span><span class="token punctuation">,</span><span class="token number">0</span><span class="token punctuation">]</span>  <span class="token comment">#截取整个蓝色通道</span>

<span class="token comment"># 通道拆分</span>
b<span class="token punctuation">,</span> g<span class="token punctuation">,</span> r <span class="token operator">=</span> cv<span class="token punctuation">.</span>split<span class="token punctuation">(</span>img<span class="token punctuation">)</span>
<span class="token comment"># 通道合并</span>
img <span class="token operator">=</span> cv<span class="token punctuation">.</span>merge<span class="token punctuation">(</span><span class="token punctuation">(</span>b<span class="token punctuation">,</span> g<span class="token punctuation">,</span> r<span class="token punctuation">)</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<h3 id="2-5-添加边界-padding"><a href="#2-5-添加边界-padding" class="headerlink" title="2.5 添加边界(padding)　　"></a>2.5 添加边界(padding)　　</h3><div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python">cv<span class="token punctuation">.</span>copyMakeBorder<span class="token punctuation">(</span><span class="token punctuation">)</span>
    参数：
        img<span class="token punctuation">:</span>图像对象
        top<span class="token punctuation">,</span> bottom<span class="token punctuation">,</span> left<span class="token punctuation">,</span> right<span class="token punctuation">:</span> 上下左右边界宽度，单位为像素值
        borderType<span class="token punctuation">:</span>
            cv<span class="token punctuation">.</span>BORDER_CONSTANT<span class="token punctuation">,</span> 带颜色的边界，需要传入另外一个颜色值
            cv<span class="token punctuation">.</span>BORDER_REFLECT<span class="token punctuation">,</span> 边缘元素的镜像反射做为边界
            cv<span class="token punctuation">.</span>BORDER_REFLECT_101<span class="token operator">/</span>cv<span class="token punctuation">.</span>BORDER_DEFAULT
            cv<span class="token punctuation">.</span>BORDER_REPLICATE<span class="token punctuation">,</span> 边缘元素的复制做为边界
            CV<span class="token punctuation">.</span>BORDER_WRAP
        value<span class="token punctuation">:</span> borderType为cv<span class="token punctuation">.</span>BORDER_CONSTANT时，传入的边界颜色值，如<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token number">255</span><span class="token punctuation">,</span><span class="token number">0</span><span class="token punctuation">]</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p>使用示例：</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token keyword">import</span> cv2 <span class="token keyword">as</span> cv
<span class="token keyword">import</span> matplotlib<span class="token punctuation">.</span>pyplot <span class="token keyword">as</span> plt

img2 <span class="token operator">=</span> cv<span class="token punctuation">.</span>imread<span class="token punctuation">(</span><span class="token string">r"./image/dog.jpg"</span><span class="token punctuation">)</span>
img <span class="token operator">=</span> cv<span class="token punctuation">.</span>cvtColor<span class="token punctuation">(</span>img2<span class="token punctuation">,</span> cv<span class="token punctuation">.</span>COLOR_BGR2RGB<span class="token punctuation">)</span>  <span class="token comment"># matplotlib的图像为RGB格式</span>
constant <span class="token operator">=</span> cv<span class="token punctuation">.</span>copyMakeBorder<span class="token punctuation">(</span>img<span class="token punctuation">,</span> <span class="token number">20</span><span class="token punctuation">,</span> <span class="token number">20</span><span class="token punctuation">,</span> <span class="token number">20</span><span class="token punctuation">,</span> <span class="token number">20</span><span class="token punctuation">,</span> cv<span class="token punctuation">.</span>BORDER_CONSTANT<span class="token punctuation">,</span> value<span class="token operator">=</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">255</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">)</span>  <span class="token comment"># 绿色</span>
reflect <span class="token operator">=</span> cv<span class="token punctuation">.</span>copyMakeBorder<span class="token punctuation">(</span>img<span class="token punctuation">,</span> <span class="token number">20</span><span class="token punctuation">,</span> <span class="token number">20</span><span class="token punctuation">,</span> <span class="token number">20</span><span class="token punctuation">,</span> <span class="token number">20</span><span class="token punctuation">,</span> cv<span class="token punctuation">.</span>BORDER_REFLECT<span class="token punctuation">)</span>
reflect01 <span class="token operator">=</span> cv<span class="token punctuation">.</span>copyMakeBorder<span class="token punctuation">(</span>img<span class="token punctuation">,</span> <span class="token number">20</span><span class="token punctuation">,</span> <span class="token number">20</span><span class="token punctuation">,</span> <span class="token number">20</span><span class="token punctuation">,</span> <span class="token number">20</span><span class="token punctuation">,</span> cv<span class="token punctuation">.</span>BORDER_REFLECT_101<span class="token punctuation">)</span>
replicate <span class="token operator">=</span> cv<span class="token punctuation">.</span>copyMakeBorder<span class="token punctuation">(</span>img<span class="token punctuation">,</span> <span class="token number">20</span><span class="token punctuation">,</span> <span class="token number">20</span><span class="token punctuation">,</span> <span class="token number">20</span><span class="token punctuation">,</span> <span class="token number">20</span><span class="token punctuation">,</span> cv<span class="token punctuation">.</span>BORDER_REPLICATE<span class="token punctuation">)</span>
wrap <span class="token operator">=</span> cv<span class="token punctuation">.</span>copyMakeBorder<span class="token punctuation">(</span>img<span class="token punctuation">,</span> <span class="token number">20</span><span class="token punctuation">,</span> <span class="token number">20</span><span class="token punctuation">,</span> <span class="token number">20</span><span class="token punctuation">,</span> <span class="token number">20</span><span class="token punctuation">,</span> cv<span class="token punctuation">.</span>BORDER_WRAP<span class="token punctuation">)</span>
titles <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token string">"constant"</span><span class="token punctuation">,</span> <span class="token string">"reflect"</span><span class="token punctuation">,</span> <span class="token string">"reflect01"</span><span class="token punctuation">,</span> <span class="token string">"replicate"</span><span class="token punctuation">,</span> <span class="token string">"wrap"</span><span class="token punctuation">]</span>
images <span class="token operator">=</span> <span class="token punctuation">[</span>constant<span class="token punctuation">,</span> reflect<span class="token punctuation">,</span> reflect01<span class="token punctuation">,</span> replicate<span class="token punctuation">,</span> wrap<span class="token punctuation">]</span>

<span class="token keyword">for</span> i <span class="token keyword">in</span> <span class="token builtin">range</span><span class="token punctuation">(</span><span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
    plt<span class="token punctuation">.</span>subplot<span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> i <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>imshow<span class="token punctuation">(</span>images<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>title<span class="token punctuation">(</span>titles<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span>
    plt<span class="token punctuation">.</span>xticks<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>yticks<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>show<span class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p><img src="https://cdn.nlark.com/yuque/0/2020/png/448115/1603440178298-913f9e4c-6d5c-43a7-941c-ec6654217258.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_15%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#height=373&amp;id=zbLbG&amp;originHeight=373&amp;originWidth=515&amp;originalType=binary∶=1&amp;size=0&amp;status=done&amp;style=none&amp;width=515" srcset="/img/loading.gif" lazyload alt=""></p>
<h3 id="2-6-像素算术运算"><a href="#2-6-像素算术运算" class="headerlink" title="2.6 像素算术运算"></a>2.6 像素算术运算</h3><p><strong>cv.add() </strong> 相加的两个图片，应该有相同的大小和通道<br>你可以使用 OpenCV 的 cv.add()函数把两幅图像相加，或者可以简单地通过 numpy 操作添加两个图像，如 res = img1 + img2。两个图像应该具有相同的大小和类型，或者第二个图像可以是标量值。<br><strong>注意：OpenCV 加法和 Numpy 加法之间存在差异。OpenCV 的加法是饱和操作，而 Numpy 添加是模运算。</strong></p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python">cv<span class="token punctuation">.</span>add<span class="token punctuation">(</span><span class="token punctuation">)</span>
    参数：
        img1<span class="token punctuation">:</span>图片对象<span class="token number">1</span>
        img2<span class="token punctuation">:</span>图片对象<span class="token number">2</span>
        mask<span class="token punctuation">:</span><span class="token boolean">None</span> （掩膜，一般用灰度图做掩膜，img1和img2相加后，和掩膜与运算，从而达到掩盖部分区域的目的）
        dtype<span class="token punctuation">:</span><span class="token operator">-</span><span class="token number">1</span>

注意：图像相加时应该用cv<span class="token punctuation">.</span>add<span class="token punctuation">(</span>img1<span class="token punctuation">,</span>img2<span class="token punctuation">)</span>代替img1<span class="token operator">+</span>img2
<span class="token operator">>></span><span class="token operator">></span> x <span class="token operator">=</span> np<span class="token punctuation">.</span>uint8<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token number">250</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
<span class="token operator">>></span><span class="token operator">></span> y <span class="token operator">=</span> np<span class="token punctuation">.</span>uint8<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token number">10</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
<span class="token operator">>></span><span class="token operator">></span> <span class="token keyword">print</span> cv<span class="token punctuation">.</span>add<span class="token punctuation">(</span>x<span class="token punctuation">,</span>y<span class="token punctuation">)</span> <span class="token comment"># 250+10 = 260 => 255  #相加，opencv超过255的截取为255</span>
<span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token number">255</span><span class="token punctuation">]</span><span class="token punctuation">]</span>
<span class="token operator">>></span><span class="token operator">></span> <span class="token keyword">print</span> x<span class="token operator">+</span>y          <span class="token comment"># 250+10 = 260 % 256 = 4  #相加，np超过255的会取模运算 （uint8只能表示0-255，所以取模）</span>
<span class="token punctuation">[</span><span class="token number">4</span><span class="token punctuation">]</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p>使用示例：图一无掩膜，图二有掩膜</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token keyword">import</span> numpy <span class="token keyword">as</span> np
<span class="token keyword">import</span> cv2 <span class="token keyword">as</span> cv
<span class="token keyword">import</span> matplotlib<span class="token punctuation">.</span>pyplot <span class="token keyword">as</span> plt

<span class="token comment"># 1 读取图像</span>
img1 <span class="token operator">=</span> cv<span class="token punctuation">.</span>imread<span class="token punctuation">(</span><span class="token string">"./image/view.jpg"</span><span class="token punctuation">)</span>
img2 <span class="token operator">=</span> cv<span class="token punctuation">.</span>imread<span class="token punctuation">(</span><span class="token string">"./image/rain.jpg"</span><span class="token punctuation">)</span>

<span class="token comment"># 2 加法操作</span>
img3 <span class="token operator">=</span> cv<span class="token punctuation">.</span>add<span class="token punctuation">(</span>img1<span class="token punctuation">,</span> img2<span class="token punctuation">)</span>  <span class="token comment"># cv中的加法</span>
img4 <span class="token operator">=</span> img1 <span class="token operator">+</span> img2  <span class="token comment"># 直接相加</span>

<span class="token comment"># 3 图像显示</span>
fig<span class="token punctuation">,</span> axes <span class="token operator">=</span> plt<span class="token punctuation">.</span>subplots<span class="token punctuation">(</span>nrows<span class="token operator">=</span><span class="token number">1</span><span class="token punctuation">,</span> ncols<span class="token operator">=</span><span class="token number">2</span><span class="token punctuation">,</span> figsize<span class="token operator">=</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">,</span> <span class="token number">8</span><span class="token punctuation">)</span><span class="token punctuation">,</span> dpi<span class="token operator">=</span><span class="token number">100</span><span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>imshow<span class="token punctuation">(</span>img3<span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token punctuation">,</span> <span class="token punctuation">:</span><span class="token punctuation">,</span> <span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>set_title<span class="token punctuation">(</span><span class="token string">"cv中的加法"</span><span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">.</span>imshow<span class="token punctuation">(</span>img4<span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token punctuation">,</span> <span class="token punctuation">:</span><span class="token punctuation">,</span> <span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">.</span>set_title<span class="token punctuation">(</span><span class="token string">"直接相加"</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>show<span class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p>结果如下所示：<br><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617372984582-86e680c1-87d3-4230-b2be-68ce9763a4b8.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_20%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png"><strong>cv.addWeight(): </strong>两张图片相加，分别给予不同权重，实现图片融合和透明背景等效果<br>这其实也是加法，但是不同的是两幅图像的权重不同，这就会给人一种混合或者透明的感觉。图像混合的计算公式如下：</p>
<blockquote>
<p>g(x) = (1−α)f0(x) + αf1(x)</p>
</blockquote>
<p>通过修改 α 的值（0 → 1），可以实现非常炫酷的混合。<br>现在我们把两幅图混合在一起。第一幅图的权重是 0.7，第二幅图的权重是 0.3。函数 cv2.addWeighted()可以按下面的公式对图片进行混合操作。</p>
<blockquote>
<p>dst = α⋅img1 + β⋅img2 + γ</p>
</blockquote>
<p>这里 γ 取为零。</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python">cv<span class="token punctuation">.</span>addWeighted<span class="token punctuation">(</span><span class="token punctuation">)</span> 两张图片相加，分别给予不同权重，实现图片融合和透明背景等效果
    参数：
        img1<span class="token punctuation">:</span>图片对象<span class="token number">1</span>
        alpha<span class="token punctuation">:</span>img1的权重
        img2<span class="token punctuation">:</span>图片对象<span class="token number">2</span>
        beta<span class="token punctuation">:</span>img1的权重
        gamma：常量值，图像相加后再加上常量值
        dtype：返回图像的数据类型，默认为<span class="token operator">-</span><span class="token number">1</span>，和img1一样
    <span class="token punctuation">(</span>img1<span class="token operator">*</span>alpha<span class="token operator">+</span>img2<span class="token operator">*</span>beta<span class="token operator">+</span>gamma<span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p>使用示例：</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token keyword">import</span> numpy <span class="token keyword">as</span> np
<span class="token keyword">import</span> cv2 <span class="token keyword">as</span> cv
<span class="token keyword">import</span> matplotlib<span class="token punctuation">.</span>pyplot <span class="token keyword">as</span> plt

<span class="token comment"># 1 读取图像</span>
img1 <span class="token operator">=</span> cv<span class="token punctuation">.</span>imread<span class="token punctuation">(</span><span class="token string">"./image/view.jpg"</span><span class="token punctuation">)</span>
img2 <span class="token operator">=</span> cv<span class="token punctuation">.</span>imread<span class="token punctuation">(</span><span class="token string">"./image/rain.jpg"</span><span class="token punctuation">)</span>

<span class="token comment"># 2 图像混合</span>
img3 <span class="token operator">=</span> cv<span class="token punctuation">.</span>addWeighted<span class="token punctuation">(</span>img1<span class="token punctuation">,</span> <span class="token number">0.7</span><span class="token punctuation">,</span> img2<span class="token punctuation">,</span> <span class="token number">0.3</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span>

<span class="token comment"># 3 图像显示</span>
plt<span class="token punctuation">.</span>figure<span class="token punctuation">(</span>figsize<span class="token operator">=</span><span class="token punctuation">(</span><span class="token number">8</span><span class="token punctuation">,</span> <span class="token number">8</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>imshow<span class="token punctuation">(</span>img3<span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token punctuation">,</span> <span class="token punctuation">:</span><span class="token punctuation">,</span> <span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>show<span class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617373117773-11493931-ec15-4823-a231-6f286466d6bf.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_19%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png"></p>
<h3 id="2-7-图像位运算"><a href="#2-7-图像位运算" class="headerlink" title="2.7 图像位运算"></a>2.7 图像位运算</h3><p><strong>btwise_and(), bitwise_or(), bitwise_not(), bitwise_xor()</strong></p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python">cv<span class="token punctuation">.</span>btwise_and<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> 与运算
    参数：
        img1<span class="token punctuation">:</span>图片对象<span class="token number">1</span>
        img2<span class="token punctuation">:</span>图片对象<span class="token number">2</span>
        mask<span class="token punctuation">:</span>掩膜
    cv<span class="token punctuation">.</span>bitwise_or<span class="token punctuation">(</span><span class="token punctuation">)</span>：或运算
    参数：
        img1<span class="token punctuation">:</span>图片对象<span class="token number">1</span>
        img2<span class="token punctuation">:</span>图片对象<span class="token number">2</span>
        mask<span class="token punctuation">:</span>掩膜
    cv<span class="token punctuation">.</span>bitwise_not<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> 非运算
        img1<span class="token punctuation">:</span>图片对象<span class="token number">1</span>
        mask<span class="token punctuation">:</span>掩膜
    cv<span class="token punctuation">.</span>bitwise_xor<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span>异或运算，相同为<span class="token number">1</span>，不同为<span class="token number">0</span>（<span class="token number">1</span><span class="token operator">^</span><span class="token number">1</span><span class="token operator">=</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token number">1</span><span class="token operator">^</span><span class="token number">0</span><span class="token operator">=</span><span class="token number">1</span>）
        img1<span class="token punctuation">:</span>图片对象<span class="token number">1</span>
        img2<span class="token punctuation">:</span>图片对象<span class="token number">2</span>
        mask<span class="token punctuation">:</span>掩膜<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p>使用示例：将 logo 图片移动到足球图片中，需要截取 logo 图片的前景和足球图片 ROI 的背景，然后叠加，效果如下：</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token keyword">import</span> cv2 <span class="token keyword">as</span> cv
<span class="token keyword">import</span> matplotlib<span class="token punctuation">.</span>pyplot <span class="token keyword">as</span> plt

img1 <span class="token operator">=</span> cv<span class="token punctuation">.</span>imread<span class="token punctuation">(</span><span class="token string">r"./image/logo.png"</span><span class="token punctuation">)</span>
rows<span class="token punctuation">,</span>cols <span class="token operator">=</span> img1<span class="token punctuation">.</span>shape<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">:</span><span class="token number">2</span><span class="token punctuation">]</span>
img2 <span class="token operator">=</span> cv<span class="token punctuation">.</span>imread<span class="token punctuation">(</span><span class="token string">r"./image/Messi.jpg"</span><span class="token punctuation">)</span>
roi <span class="token operator">=</span> img2<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">:</span>rows<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">:</span>cols<span class="token punctuation">]</span>
img1_gray <span class="token operator">=</span> cv<span class="token punctuation">.</span>cvtColor<span class="token punctuation">(</span>img1<span class="token punctuation">,</span>cv<span class="token punctuation">.</span>COLOR_BGR2GRAY<span class="token punctuation">)</span>

ret<span class="token punctuation">,</span>img1_thres <span class="token operator">=</span> cv<span class="token punctuation">.</span>threshold<span class="token punctuation">(</span>img1_gray<span class="token punctuation">,</span> <span class="token number">200</span><span class="token punctuation">,</span> <span class="token number">255</span><span class="token punctuation">,</span>cv<span class="token punctuation">.</span>THRESH_BINARY_INV<span class="token punctuation">)</span>
img1_fg <span class="token operator">=</span>cv<span class="token punctuation">.</span>add<span class="token punctuation">(</span>img1<span class="token punctuation">,</span> img1<span class="token punctuation">,</span> mask<span class="token operator">=</span>img1_thres<span class="token punctuation">)</span>    <span class="token comment">#拿到logo图案的前景</span>

img1_thres_inv <span class="token operator">=</span> cv<span class="token punctuation">.</span>bitwise_not<span class="token punctuation">(</span>img1_thres<span class="token punctuation">)</span>
roi_bg <span class="token operator">=</span> cv<span class="token punctuation">.</span>add<span class="token punctuation">(</span>roi<span class="token punctuation">,</span> roi<span class="token punctuation">,</span>mask<span class="token operator">=</span>img1_thres_inv<span class="token punctuation">)</span>  <span class="token comment">#拿到roi图案的背景</span>

img_add <span class="token operator">=</span> cv<span class="token punctuation">.</span>add<span class="token punctuation">(</span>img1_fg<span class="token punctuation">,</span> roi_bg<span class="token punctuation">)</span>     <span class="token comment">#背景和前景相加</span>
img2<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">:</span>rows<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">:</span>cols<span class="token punctuation">]</span> <span class="token operator">=</span> img_add

cv<span class="token punctuation">.</span>imshow<span class="token punctuation">(</span><span class="token string">"gray"</span><span class="token punctuation">,</span> img1_gray<span class="token punctuation">)</span>
cv<span class="token punctuation">.</span>imshow<span class="token punctuation">(</span><span class="token string">"thres"</span><span class="token punctuation">,</span> img1_thres<span class="token punctuation">)</span>
cv<span class="token punctuation">.</span>imshow<span class="token punctuation">(</span><span class="token string">"fg"</span><span class="token punctuation">,</span> img1_fg<span class="token punctuation">)</span>
cv<span class="token punctuation">.</span>imshow<span class="token punctuation">(</span><span class="token string">"tinv"</span><span class="token punctuation">,</span> img1_thres_inv<span class="token punctuation">)</span>
cv<span class="token punctuation">.</span>imshow<span class="token punctuation">(</span><span class="token string">"roi_bg"</span><span class="token punctuation">,</span> roi_bg<span class="token punctuation">)</span>
cv<span class="token punctuation">.</span>imshow<span class="token punctuation">(</span><span class="token string">"img_add"</span><span class="token punctuation">,</span> img_add<span class="token punctuation">)</span>
cv<span class="token punctuation">.</span>imshow<span class="token punctuation">(</span><span class="token string">"img2"</span><span class="token punctuation">,</span> img2<span class="token punctuation">)</span>
cv<span class="token punctuation">.</span>waitKey<span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span>
cv<span class="token punctuation">.</span>destroyAllWindows<span class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p><img src="https://cdn.nlark.com/yuque/0/2020/png/448115/1603440178303-6873a51b-276b-4905-9624-0a952707553f.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_32%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#height=462&amp;id=UTuXW&amp;originHeight=462&amp;originWidth=1114&amp;originalType=binary∶=1&amp;size=0&amp;status=done&amp;style=none&amp;width=1114" srcset="/img/loading.gif" lazyload alt=""></p>
<h3 id="2-8-性能评价"><a href="#2-8-性能评价" class="headerlink" title="2.8 性能评价　"></a>2.8 性能评价　</h3><p><strong>cv.getTickCount()：</strong> 获得时钟次数<br><strong>cv.getTickFrequency()：</strong>获得时钟频率 （每秒振动次数）</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python">img1 <span class="token operator">=</span> cv<span class="token punctuation">.</span>imread<span class="token punctuation">(</span><span class="token string">'messi5.jpg'</span><span class="token punctuation">)</span>

e1 <span class="token operator">=</span> cv<span class="token punctuation">.</span>getTickCount<span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token keyword">for</span> i <span class="token keyword">in</span> <span class="token builtin">xrange</span><span class="token punctuation">(</span><span class="token number">5</span><span class="token punctuation">,</span><span class="token number">49</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
    img1 <span class="token operator">=</span> cv<span class="token punctuation">.</span>medianBlur<span class="token punctuation">(</span>img1<span class="token punctuation">,</span>i<span class="token punctuation">)</span>
e2 <span class="token operator">=</span> cv<span class="token punctuation">.</span>getTickCount<span class="token punctuation">(</span><span class="token punctuation">)</span>
t <span class="token operator">=</span> <span class="token punctuation">(</span>e2 <span class="token operator">-</span> e1<span class="token punctuation">)</span><span class="token operator">/</span>cv<span class="token punctuation">.</span>getTickFrequency<span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token keyword">print</span><span class="token punctuation">(</span>t<span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<h3 id="2-9-绑定-trackbar-到图像"><a href="#2-9-绑定-trackbar-到图像" class="headerlink" title="2.9 绑定 trackbar 到图像"></a>2.9 绑定 trackbar 到图像</h3><p><strong>cv.createTrackbar()</strong><br><strong>cv.getTrackbarPos()</strong></p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python">cv<span class="token punctuation">.</span>createTrackbar<span class="token punctuation">(</span><span class="token punctuation">)</span> 为窗口添加trackbar
    参数：
        trackbarname<span class="token punctuation">:</span> trackbar的名字
        winname<span class="token punctuation">:</span> 窗口的名字
        value<span class="token punctuation">:</span> trackbar创建时的值
        count：trackbar能设置的最大值，最小值总为<span class="token number">0</span>
        onChange：trackbar值发生变化时的回调函数，trackbar的值作为参数传给onchange

cv<span class="token punctuation">.</span>getTrackbarPos<span class="token punctuation">(</span><span class="token punctuation">)</span> 获取某个窗口中trackbar的值
    参数：
        trackbarname<span class="token punctuation">:</span> trackbar的名字
        winname<span class="token punctuation">:</span> 窗口的名字<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p>使用示例：通过改变 trackbar 的值，来寻找最优的 mask 范围，从而识别出图片中蓝色的瓶盖</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token keyword">import</span> cv2 <span class="token keyword">as</span> cv
<span class="token keyword">import</span> numpy <span class="token keyword">as</span> np

<span class="token keyword">def</span> <span class="token function">nothing</span><span class="token punctuation">(</span>args<span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token keyword">pass</span>

img <span class="token operator">=</span> cv<span class="token punctuation">.</span>imread<span class="token punctuation">(</span><span class="token string">r"./image/frame.png"</span><span class="token punctuation">)</span>
img_hsv <span class="token operator">=</span> cv<span class="token punctuation">.</span>cvtColor<span class="token punctuation">(</span>img<span class="token punctuation">,</span>cv<span class="token punctuation">.</span>COLOR_BGR2HSV<span class="token punctuation">)</span>
cv<span class="token punctuation">.</span>namedWindow<span class="token punctuation">(</span><span class="token string">'tracks'</span><span class="token punctuation">)</span>
cv<span class="token punctuation">.</span>createTrackbar<span class="token punctuation">(</span><span class="token string">"LH"</span><span class="token punctuation">,</span><span class="token string">"tracks"</span><span class="token punctuation">,</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token number">255</span><span class="token punctuation">,</span>nothing<span class="token punctuation">)</span>
cv<span class="token punctuation">.</span>createTrackbar<span class="token punctuation">(</span><span class="token string">"LS"</span><span class="token punctuation">,</span><span class="token string">"tracks"</span><span class="token punctuation">,</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token number">255</span><span class="token punctuation">,</span>nothing<span class="token punctuation">)</span>
cv<span class="token punctuation">.</span>createTrackbar<span class="token punctuation">(</span><span class="token string">"LV"</span><span class="token punctuation">,</span><span class="token string">"tracks"</span><span class="token punctuation">,</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token number">255</span><span class="token punctuation">,</span>nothing<span class="token punctuation">)</span>

cv<span class="token punctuation">.</span>createTrackbar<span class="token punctuation">(</span><span class="token string">"UH"</span><span class="token punctuation">,</span><span class="token string">"tracks"</span><span class="token punctuation">,</span><span class="token number">255</span><span class="token punctuation">,</span><span class="token number">255</span><span class="token punctuation">,</span>nothing<span class="token punctuation">)</span>
cv<span class="token punctuation">.</span>createTrackbar<span class="token punctuation">(</span><span class="token string">"US"</span><span class="token punctuation">,</span><span class="token string">"tracks"</span><span class="token punctuation">,</span><span class="token number">255</span><span class="token punctuation">,</span><span class="token number">255</span><span class="token punctuation">,</span>nothing<span class="token punctuation">)</span>
cv<span class="token punctuation">.</span>createTrackbar<span class="token punctuation">(</span><span class="token string">"UV"</span><span class="token punctuation">,</span><span class="token string">"tracks"</span><span class="token punctuation">,</span><span class="token number">255</span><span class="token punctuation">,</span><span class="token number">255</span><span class="token punctuation">,</span>nothing<span class="token punctuation">)</span>

<span class="token comment"># switch = "0:OFF \n1:ON"</span>
<span class="token comment"># cv.createTrackbar(switch,"tracks",0,1,nothing)</span>

<span class="token keyword">while</span> <span class="token boolean">True</span><span class="token punctuation">:</span>

    l_h <span class="token operator">=</span> cv<span class="token punctuation">.</span>getTrackbarPos<span class="token punctuation">(</span><span class="token string">"LH"</span><span class="token punctuation">,</span><span class="token string">"tracks"</span><span class="token punctuation">)</span>
    l_s <span class="token operator">=</span> cv<span class="token punctuation">.</span>getTrackbarPos<span class="token punctuation">(</span><span class="token string">"LS"</span><span class="token punctuation">,</span><span class="token string">"tracks"</span><span class="token punctuation">)</span>
    l_v <span class="token operator">=</span> cv<span class="token punctuation">.</span>getTrackbarPos<span class="token punctuation">(</span><span class="token string">"LV"</span><span class="token punctuation">,</span><span class="token string">"tracks"</span><span class="token punctuation">)</span>
    u_h <span class="token operator">=</span> cv<span class="token punctuation">.</span>getTrackbarPos<span class="token punctuation">(</span><span class="token string">"UH"</span><span class="token punctuation">,</span><span class="token string">"tracks"</span><span class="token punctuation">)</span>
    u_s <span class="token operator">=</span> cv<span class="token punctuation">.</span>getTrackbarPos<span class="token punctuation">(</span><span class="token string">"US"</span><span class="token punctuation">,</span><span class="token string">"tracks"</span><span class="token punctuation">)</span>
    u_v <span class="token operator">=</span> cv<span class="token punctuation">.</span>getTrackbarPos<span class="token punctuation">(</span><span class="token string">"UV"</span><span class="token punctuation">,</span><span class="token string">"tracks"</span><span class="token punctuation">)</span>

    lower_b <span class="token operator">=</span> np<span class="token punctuation">.</span>array<span class="token punctuation">(</span><span class="token punctuation">[</span>l_h<span class="token punctuation">,</span>l_s<span class="token punctuation">,</span>l_v<span class="token punctuation">]</span><span class="token punctuation">)</span>
    upper_b <span class="token operator">=</span> np<span class="token punctuation">.</span>array<span class="token punctuation">(</span><span class="token punctuation">[</span>u_h<span class="token punctuation">,</span>u_s<span class="token punctuation">,</span>u_v<span class="token punctuation">]</span><span class="token punctuation">)</span>

    mask <span class="token operator">=</span> cv<span class="token punctuation">.</span>inRange<span class="token punctuation">(</span>img_hsv<span class="token punctuation">,</span>lower_b<span class="token punctuation">,</span>upper_b<span class="token punctuation">)</span>
    res <span class="token operator">=</span> cv<span class="token punctuation">.</span>add<span class="token punctuation">(</span>img<span class="token punctuation">,</span>img<span class="token punctuation">,</span>mask<span class="token operator">=</span>mask<span class="token punctuation">)</span>

    cv<span class="token punctuation">.</span>imshow<span class="token punctuation">(</span><span class="token string">"img"</span><span class="token punctuation">,</span>img<span class="token punctuation">)</span>
    cv<span class="token punctuation">.</span>imshow<span class="token punctuation">(</span><span class="token string">"mask"</span><span class="token punctuation">,</span>mask<span class="token punctuation">)</span>
    cv<span class="token punctuation">.</span>imshow<span class="token punctuation">(</span><span class="token string">"res"</span><span class="token punctuation">,</span>res<span class="token punctuation">)</span>
    k <span class="token operator">=</span> cv<span class="token punctuation">.</span>waitKey<span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span>
    <span class="token keyword">if</span> k<span class="token operator">==</span><span class="token number">27</span><span class="token punctuation">:</span>
        <span class="token keyword">break</span>


cv<span class="token punctuation">.</span>destroyAllWindows<span class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p><img src="https://cdn.nlark.com/yuque/0/2020/png/448115/1603440178411-8f454c38-00e2-471f-b55c-a685bd81dce1.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_11%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#height=227&amp;id=GwejM&amp;originHeight=227&amp;originWidth=242&amp;originalType=binary∶=1&amp;size=0&amp;status=done&amp;style=none&amp;width=242" srcset="/img/loading.gif" lazyload alt=""></p>
<p><img src="https://cdn.nlark.com/yuque/0/2020/png/448115/1603440178513-401cc885-25b5-4d3f-9e47-12bb8a41e1de.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_26%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#height=357&amp;id=ZRzWN&amp;originHeight=357&amp;originWidth=903&amp;originalType=binary∶=1&amp;size=0&amp;status=done&amp;style=none&amp;width=903" srcset="/img/loading.gif" lazyload alt=""><br>再来一个例子</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token keyword">import</span> cv2 <span class="token keyword">as</span> cv
<span class="token keyword">import</span> numpy <span class="token keyword">as</span> np


<span class="token keyword">def</span> <span class="token function">empty</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token keyword">pass</span>


<span class="token keyword">def</span> <span class="token function">stackImages</span><span class="token punctuation">(</span>scale<span class="token punctuation">,</span> imgArray<span class="token punctuation">)</span><span class="token punctuation">:</span>
    rows <span class="token operator">=</span> <span class="token builtin">len</span><span class="token punctuation">(</span>imgArray<span class="token punctuation">)</span>
    cols <span class="token operator">=</span> <span class="token builtin">len</span><span class="token punctuation">(</span>imgArray<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
    rowsAvailable <span class="token operator">=</span> <span class="token builtin">isinstance</span><span class="token punctuation">(</span>imgArray<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token builtin">list</span><span class="token punctuation">)</span>
    width <span class="token operator">=</span> imgArray<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>shape<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span>
    height <span class="token operator">=</span> imgArray<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>shape<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span>
    <span class="token keyword">if</span> rowsAvailable<span class="token punctuation">:</span>
        <span class="token keyword">for</span> x <span class="token keyword">in</span> <span class="token builtin">range</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> rows<span class="token punctuation">)</span><span class="token punctuation">:</span>
            <span class="token keyword">for</span> y <span class="token keyword">in</span> <span class="token builtin">range</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> cols<span class="token punctuation">)</span><span class="token punctuation">:</span>
                <span class="token keyword">if</span> imgArray<span class="token punctuation">[</span>x<span class="token punctuation">]</span><span class="token punctuation">[</span>y<span class="token punctuation">]</span><span class="token punctuation">.</span>shape<span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token number">2</span><span class="token punctuation">]</span> <span class="token operator">==</span> imgArray<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>shape<span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token number">2</span><span class="token punctuation">]</span><span class="token punctuation">:</span>
                    imgArray<span class="token punctuation">[</span>x<span class="token punctuation">]</span><span class="token punctuation">[</span>y<span class="token punctuation">]</span> <span class="token operator">=</span> cv<span class="token punctuation">.</span>resize<span class="token punctuation">(</span>imgArray<span class="token punctuation">[</span>x<span class="token punctuation">]</span><span class="token punctuation">[</span>y<span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token boolean">None</span><span class="token punctuation">,</span> scale<span class="token punctuation">,</span> scale<span class="token punctuation">)</span>
                <span class="token keyword">else</span><span class="token punctuation">:</span>
                    imgArray<span class="token punctuation">[</span>x<span class="token punctuation">]</span><span class="token punctuation">[</span>y<span class="token punctuation">]</span> <span class="token operator">=</span> cv<span class="token punctuation">.</span>resize<span class="token punctuation">(</span>imgArray<span class="token punctuation">[</span>x<span class="token punctuation">]</span><span class="token punctuation">[</span>y<span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">(</span>imgArray<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>shape<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">,</span> imgArray<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>shape<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token boolean">None</span><span class="token punctuation">,</span>
                                               scale<span class="token punctuation">,</span> scale<span class="token punctuation">)</span>
                <span class="token keyword">if</span> <span class="token builtin">len</span><span class="token punctuation">(</span>imgArray<span class="token punctuation">[</span>x<span class="token punctuation">]</span><span class="token punctuation">[</span>y<span class="token punctuation">]</span><span class="token punctuation">.</span>shape<span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token number">2</span><span class="token punctuation">:</span> imgArray<span class="token punctuation">[</span>x<span class="token punctuation">]</span><span class="token punctuation">[</span>y<span class="token punctuation">]</span> <span class="token operator">=</span> cv<span class="token punctuation">.</span>cvtColor<span class="token punctuation">(</span>imgArray<span class="token punctuation">[</span>x<span class="token punctuation">]</span><span class="token punctuation">[</span>y<span class="token punctuation">]</span><span class="token punctuation">,</span> cv<span class="token punctuation">.</span>COLOR_GRAY2BGR<span class="token punctuation">)</span>
        imageBlank <span class="token operator">=</span> np<span class="token punctuation">.</span>zeros<span class="token punctuation">(</span><span class="token punctuation">(</span>height<span class="token punctuation">,</span> width<span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">,</span> np<span class="token punctuation">.</span>uint8<span class="token punctuation">)</span>
        hor <span class="token operator">=</span> <span class="token punctuation">[</span>imageBlank<span class="token punctuation">]</span> <span class="token operator">*</span> rows
        hor_con <span class="token operator">=</span> <span class="token punctuation">[</span>imageBlank<span class="token punctuation">]</span> <span class="token operator">*</span> rows
        <span class="token keyword">for</span> x <span class="token keyword">in</span> <span class="token builtin">range</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> rows<span class="token punctuation">)</span><span class="token punctuation">:</span>
            hor<span class="token punctuation">[</span>x<span class="token punctuation">]</span> <span class="token operator">=</span> np<span class="token punctuation">.</span>hstack<span class="token punctuation">(</span>imgArray<span class="token punctuation">[</span>x<span class="token punctuation">]</span><span class="token punctuation">)</span>
        ver <span class="token operator">=</span> np<span class="token punctuation">.</span>vstack<span class="token punctuation">(</span>hor<span class="token punctuation">)</span>
    <span class="token keyword">else</span><span class="token punctuation">:</span>
        <span class="token keyword">for</span> x <span class="token keyword">in</span> <span class="token builtin">range</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> rows<span class="token punctuation">)</span><span class="token punctuation">:</span>
            <span class="token keyword">if</span> imgArray<span class="token punctuation">[</span>x<span class="token punctuation">]</span><span class="token punctuation">.</span>shape<span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token number">2</span><span class="token punctuation">]</span> <span class="token operator">==</span> imgArray<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>shape<span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token number">2</span><span class="token punctuation">]</span><span class="token punctuation">:</span>
                imgArray<span class="token punctuation">[</span>x<span class="token punctuation">]</span> <span class="token operator">=</span> cv<span class="token punctuation">.</span>resize<span class="token punctuation">(</span>imgArray<span class="token punctuation">[</span>x<span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token boolean">None</span><span class="token punctuation">,</span> scale<span class="token punctuation">,</span> scale<span class="token punctuation">)</span>
            <span class="token keyword">else</span><span class="token punctuation">:</span>
                imgArray<span class="token punctuation">[</span>x<span class="token punctuation">]</span> <span class="token operator">=</span> cv<span class="token punctuation">.</span>resize<span class="token punctuation">(</span>imgArray<span class="token punctuation">[</span>x<span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">(</span>imgArray<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>shape<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">,</span> imgArray<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>shape<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token boolean">None</span><span class="token punctuation">,</span> scale<span class="token punctuation">,</span> scale<span class="token punctuation">)</span>
            <span class="token keyword">if</span> <span class="token builtin">len</span><span class="token punctuation">(</span>imgArray<span class="token punctuation">[</span>x<span class="token punctuation">]</span><span class="token punctuation">.</span>shape<span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token number">2</span><span class="token punctuation">:</span> imgArray<span class="token punctuation">[</span>x<span class="token punctuation">]</span> <span class="token operator">=</span> cv<span class="token punctuation">.</span>cvtColor<span class="token punctuation">(</span>imgArray<span class="token punctuation">[</span>x<span class="token punctuation">]</span><span class="token punctuation">,</span> cv<span class="token punctuation">.</span>COLOR_GRAY2BGR<span class="token punctuation">)</span>
        hor <span class="token operator">=</span> np<span class="token punctuation">.</span>hstack<span class="token punctuation">(</span>imgArray<span class="token punctuation">)</span>
        ver <span class="token operator">=</span> hor
    <span class="token keyword">return</span> ver


path <span class="token operator">=</span> <span class="token string">'Resources/lambo.png'</span>
cv<span class="token punctuation">.</span>namedWindow<span class="token punctuation">(</span><span class="token string">"TrackBars"</span><span class="token punctuation">)</span>
cv<span class="token punctuation">.</span>resizeWindow<span class="token punctuation">(</span><span class="token string">"TrackBars"</span><span class="token punctuation">,</span> <span class="token number">640</span><span class="token punctuation">,</span> <span class="token number">240</span><span class="token punctuation">)</span>
cv<span class="token punctuation">.</span>createTrackbar<span class="token punctuation">(</span><span class="token string">"Hue Min"</span><span class="token punctuation">,</span> <span class="token string">"TrackBars"</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">179</span><span class="token punctuation">,</span> empty<span class="token punctuation">)</span>
cv<span class="token punctuation">.</span>createTrackbar<span class="token punctuation">(</span><span class="token string">"Hue Max"</span><span class="token punctuation">,</span> <span class="token string">"TrackBars"</span><span class="token punctuation">,</span> <span class="token number">19</span><span class="token punctuation">,</span> <span class="token number">179</span><span class="token punctuation">,</span> empty<span class="token punctuation">)</span>
cv<span class="token punctuation">.</span>createTrackbar<span class="token punctuation">(</span><span class="token string">"Sat Min"</span><span class="token punctuation">,</span> <span class="token string">"TrackBars"</span><span class="token punctuation">,</span> <span class="token number">110</span><span class="token punctuation">,</span> <span class="token number">255</span><span class="token punctuation">,</span> empty<span class="token punctuation">)</span>
cv<span class="token punctuation">.</span>createTrackbar<span class="token punctuation">(</span><span class="token string">"Sat Max"</span><span class="token punctuation">,</span> <span class="token string">"TrackBars"</span><span class="token punctuation">,</span> <span class="token number">240</span><span class="token punctuation">,</span> <span class="token number">255</span><span class="token punctuation">,</span> empty<span class="token punctuation">)</span>
cv<span class="token punctuation">.</span>createTrackbar<span class="token punctuation">(</span><span class="token string">"Val Min"</span><span class="token punctuation">,</span> <span class="token string">"TrackBars"</span><span class="token punctuation">,</span> <span class="token number">153</span><span class="token punctuation">,</span> <span class="token number">255</span><span class="token punctuation">,</span> empty<span class="token punctuation">)</span>
cv<span class="token punctuation">.</span>createTrackbar<span class="token punctuation">(</span><span class="token string">"Val Max"</span><span class="token punctuation">,</span> <span class="token string">"TrackBars"</span><span class="token punctuation">,</span> <span class="token number">255</span><span class="token punctuation">,</span> <span class="token number">255</span><span class="token punctuation">,</span> empty<span class="token punctuation">)</span>

<span class="token keyword">while</span> <span class="token boolean">True</span><span class="token punctuation">:</span>
    img <span class="token operator">=</span> cv<span class="token punctuation">.</span>imread<span class="token punctuation">(</span>path<span class="token punctuation">)</span>
    imgHSV <span class="token operator">=</span> cv<span class="token punctuation">.</span>cvtColor<span class="token punctuation">(</span>img<span class="token punctuation">,</span> cv<span class="token punctuation">.</span>COLOR_BGR2HSV<span class="token punctuation">)</span>
    h_min <span class="token operator">=</span> cv<span class="token punctuation">.</span>getTrackbarPos<span class="token punctuation">(</span><span class="token string">"Hue Min"</span><span class="token punctuation">,</span> <span class="token string">"TrackBars"</span><span class="token punctuation">)</span>
    h_max <span class="token operator">=</span> cv<span class="token punctuation">.</span>getTrackbarPos<span class="token punctuation">(</span><span class="token string">"Hue Max"</span><span class="token punctuation">,</span> <span class="token string">"TrackBars"</span><span class="token punctuation">)</span>
    s_min <span class="token operator">=</span> cv<span class="token punctuation">.</span>getTrackbarPos<span class="token punctuation">(</span><span class="token string">"Sat Min"</span><span class="token punctuation">,</span> <span class="token string">"TrackBars"</span><span class="token punctuation">)</span>
    s_max <span class="token operator">=</span> cv<span class="token punctuation">.</span>getTrackbarPos<span class="token punctuation">(</span><span class="token string">"Sat Max"</span><span class="token punctuation">,</span> <span class="token string">"TrackBars"</span><span class="token punctuation">)</span>
    v_min <span class="token operator">=</span> cv<span class="token punctuation">.</span>getTrackbarPos<span class="token punctuation">(</span><span class="token string">"Val Min"</span><span class="token punctuation">,</span> <span class="token string">"TrackBars"</span><span class="token punctuation">)</span>
    v_max <span class="token operator">=</span> cv<span class="token punctuation">.</span>getTrackbarPos<span class="token punctuation">(</span><span class="token string">"Val Max"</span><span class="token punctuation">,</span> <span class="token string">"TrackBars"</span><span class="token punctuation">)</span>
    <span class="token keyword">print</span><span class="token punctuation">(</span>h_min<span class="token punctuation">,</span> h_max<span class="token punctuation">,</span> s_min<span class="token punctuation">,</span> s_max<span class="token punctuation">,</span> v_min<span class="token punctuation">,</span> v_max<span class="token punctuation">)</span>
    lower <span class="token operator">=</span> np<span class="token punctuation">.</span>array<span class="token punctuation">(</span><span class="token punctuation">[</span>h_min<span class="token punctuation">,</span> s_min<span class="token punctuation">,</span> v_min<span class="token punctuation">]</span><span class="token punctuation">)</span>
    upper <span class="token operator">=</span> np<span class="token punctuation">.</span>array<span class="token punctuation">(</span><span class="token punctuation">[</span>h_max<span class="token punctuation">,</span> s_max<span class="token punctuation">,</span> v_max<span class="token punctuation">]</span><span class="token punctuation">)</span>
    mask <span class="token operator">=</span> cv<span class="token punctuation">.</span>inRange<span class="token punctuation">(</span>imgHSV<span class="token punctuation">,</span> lower<span class="token punctuation">,</span> upper<span class="token punctuation">)</span>
    imgResult <span class="token operator">=</span> cv<span class="token punctuation">.</span>bitwise_and<span class="token punctuation">(</span>img<span class="token punctuation">,</span> img<span class="token punctuation">,</span> mask<span class="token operator">=</span>mask<span class="token punctuation">)</span>

    <span class="token comment"># cv.imshow("Original",img)</span>
    <span class="token comment"># cv.imshow("HSV",imgHSV)</span>
    <span class="token comment"># cv.imshow("Mask", mask)</span>
    <span class="token comment"># cv.imshow("Result", imgResult)</span>

    <span class="token comment"># stackImages图片拼接</span>
    imgStack <span class="token operator">=</span> stackImages<span class="token punctuation">(</span><span class="token number">0.6</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">[</span>img<span class="token punctuation">,</span> imgHSV<span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">[</span>mask<span class="token punctuation">,</span> imgResult<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
    cv<span class="token punctuation">.</span>imshow<span class="token punctuation">(</span><span class="token string">"Stacked Images"</span><span class="token punctuation">,</span> imgStack<span class="token punctuation">)</span>

    cv<span class="token punctuation">.</span>waitKey<span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p><img src="https://cdn.nlark.com/yuque/0/2020/png/448115/1603449379350-e2cc40f6-4e82-426c-91c0-1ad4bdf88360.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_16%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png"></p>
<h2 id="3-图像阈值化"><a href="#3-图像阈值化" class="headerlink" title="3. 图像阈值化"></a>3. 图像阈值化</h2><p><strong>cv.threshold()</strong><br><strong>cv.adaptiveThreshold()</strong></p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python">cv<span class="token punctuation">.</span>threshold<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
    参数：
        img<span class="token punctuation">:</span>图像对象，必须是灰度图
        thresh<span class="token punctuation">:</span>阈值
        maxval：最大值
        <span class="token builtin">type</span><span class="token punctuation">:</span>
            cv<span class="token punctuation">.</span>THRESH_BINARY<span class="token punctuation">:</span>     小于阈值的像素置为<span class="token number">0</span>，大于阈值的置为maxval
            cv<span class="token punctuation">.</span>THRESH_BINARY_INV： 小于阈值的像素置为maxval，大于阈值的置为<span class="token number">0</span>
            cv<span class="token punctuation">.</span>THRESH_TRUNC：      小于阈值的像素不变，大于阈值的置为thresh
            cv<span class="token punctuation">.</span>THRESH_TOZERO       小于阈值的像素置<span class="token number">0</span>，大于阈值的不变
            cv<span class="token punctuation">.</span>THRESH_TOZERO_INV   小于阈值的不变，大于阈值的像素置<span class="token number">0</span>
返回两个值
    ret<span class="token punctuation">:</span>阈值
    img：阈值化处理后的图像

cv<span class="token punctuation">.</span>adaptiveThreshold<span class="token punctuation">(</span><span class="token punctuation">)</span> 自适应阈值处理，图像不同部位采用不同的阈值进行处理
    参数：
        img<span class="token punctuation">:</span> 图像对象，<span class="token number">8</span><span class="token operator">-</span>bit单通道图
        maxValue<span class="token punctuation">:</span>最大值
        adaptiveMethod<span class="token punctuation">:</span> 自适应方法
            cv<span class="token punctuation">.</span>ADAPTIVE_THRESH_MEAN_C     ：阈值为周围像素的平均值
            cv<span class="token punctuation">.</span>ADAPTIVE_THRESH_GAUSSIAN_C <span class="token punctuation">:</span> 阈值为周围像素的高斯均值（按权重）
        threshType<span class="token punctuation">:</span>
            cv<span class="token punctuation">.</span>THRESH_BINARY<span class="token punctuation">:</span>     小于阈值的像素置为<span class="token number">0</span>，大于阈值的置为maxValuel
            cv<span class="token punctuation">.</span>THRESH_BINARY_INV<span class="token punctuation">:</span>  小于阈值的像素置为maxValue，大于阈值的置为<span class="token number">0</span>
        blocksize<span class="token punctuation">:</span> 计算阈值时，自适应的窗口大小<span class="token punctuation">,</span>必须为奇数 （如<span class="token number">3</span>：表示附近<span class="token number">3</span>个像素范围内的像素点，进行计算阈值）
        C： 常数值，通过自适应方法计算的值，减去该常数值
    <span class="token punctuation">(</span>mean value of the blocksize<span class="token operator">*</span>blocksize neighborhood of <span class="token punctuation">(</span>x<span class="token punctuation">,</span> y<span class="token punctuation">)</span> minus C<span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p>使用示例：</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token keyword">import</span> cv2 <span class="token keyword">as</span> cv
<span class="token keyword">import</span> matplotlib<span class="token punctuation">.</span>pyplot <span class="token keyword">as</span> plt

img <span class="token operator">=</span> cv<span class="token punctuation">.</span>imread<span class="token punctuation">(</span><span class="token string">r"C:./image/maze.png"</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span>

ret<span class="token punctuation">,</span> thre1 <span class="token operator">=</span> cv<span class="token punctuation">.</span>threshold<span class="token punctuation">(</span>img<span class="token punctuation">,</span> <span class="token number">127</span><span class="token punctuation">,</span> <span class="token number">255</span><span class="token punctuation">,</span> cv<span class="token punctuation">.</span>THRESH_BINARY<span class="token punctuation">)</span>
adaptive_thre1 <span class="token operator">=</span> cv<span class="token punctuation">.</span>adaptiveThreshold<span class="token punctuation">(</span>img<span class="token punctuation">,</span> <span class="token number">255</span><span class="token punctuation">,</span> cv<span class="token punctuation">.</span>ADAPTIVE_THRESH_MEAN_C<span class="token punctuation">,</span> cv<span class="token punctuation">.</span>THRESH_BINARY<span class="token punctuation">,</span> <span class="token number">7</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">)</span>
adaptive_thre2 <span class="token operator">=</span> cv<span class="token punctuation">.</span>adaptiveThreshold<span class="token punctuation">(</span>img<span class="token punctuation">,</span> <span class="token number">255</span><span class="token punctuation">,</span> cv<span class="token punctuation">.</span>ADAPTIVE_THRESH_GAUSSIAN_C<span class="token punctuation">,</span> cv<span class="token punctuation">.</span>THRESH_BINARY<span class="token punctuation">,</span> <span class="token number">7</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">)</span>

titles <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token string">"img"</span><span class="token punctuation">,</span> <span class="token string">"thre1"</span><span class="token punctuation">,</span> <span class="token string">"adaptive_thre1"</span><span class="token punctuation">,</span> <span class="token string">"adaptive_thre2"</span><span class="token punctuation">]</span>
imgs <span class="token operator">=</span> <span class="token punctuation">[</span>img<span class="token punctuation">,</span> thre1<span class="token punctuation">,</span> adaptive_thre1<span class="token punctuation">,</span> adaptive_thre2<span class="token punctuation">]</span>

<span class="token keyword">for</span> i <span class="token keyword">in</span> <span class="token builtin">range</span><span class="token punctuation">(</span><span class="token number">4</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
    plt<span class="token punctuation">.</span>subplot<span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> i <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>imshow<span class="token punctuation">(</span>imgs<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token string">"gray"</span><span class="token punctuation">)</span>
    plt<span class="token punctuation">.</span>title<span class="token punctuation">(</span>titles<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span>
    plt<span class="token punctuation">.</span>xticks<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>yticks<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>show<span class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p><img src="https://cdn.nlark.com/yuque/0/2020/png/448115/1603440178758-ce84c7ec-030b-409c-aa06-fbe1075bf145.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_16%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#height=428&amp;id=TMDSZ&amp;originHeight=428&amp;originWidth=544&amp;originalType=binary∶=1&amp;size=0&amp;status=done&amp;style=none&amp;width=544" srcset="/img/loading.gif" lazyload alt=""><br><strong>奥斯二值化（Otsu’s Binarization）</strong><br>对于一些双峰图像，奥斯二值化能找到两峰之间的像素值作为阈值，并将其返回。适用于双峰图像的阈值化，或者通过去噪而产生的双峰图像。<br>官网使用示例：</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token keyword">import</span> cv2 <span class="token keyword">as</span> cv
<span class="token keyword">import</span> numpy <span class="token keyword">as</span> np
<span class="token keyword">from</span> matplotlib <span class="token keyword">import</span> pyplot <span class="token keyword">as</span> plt

img <span class="token operator">=</span> cv<span class="token punctuation">.</span>imread<span class="token punctuation">(</span><span class="token string">'noisy2.png'</span><span class="token punctuation">,</span><span class="token number">0</span><span class="token punctuation">)</span>

<span class="token comment"># global thresholding</span>
ret1<span class="token punctuation">,</span>th1 <span class="token operator">=</span> cv<span class="token punctuation">.</span>threshold<span class="token punctuation">(</span>img<span class="token punctuation">,</span><span class="token number">127</span><span class="token punctuation">,</span><span class="token number">255</span><span class="token punctuation">,</span>cv<span class="token punctuation">.</span>THRESH_BINARY<span class="token punctuation">)</span>

<span class="token comment"># Otsu's thresholding</span>
ret2<span class="token punctuation">,</span>th2 <span class="token operator">=</span> cv<span class="token punctuation">.</span>threshold<span class="token punctuation">(</span>img<span class="token punctuation">,</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token number">255</span><span class="token punctuation">,</span>cv<span class="token punctuation">.</span>THRESH_BINARY<span class="token operator">+</span>cv<span class="token punctuation">.</span>THRESH_OTSU<span class="token punctuation">)</span>

<span class="token comment"># Otsu's thresholding after Gaussian filtering</span>
blur <span class="token operator">=</span> cv<span class="token punctuation">.</span>GaussianBlur<span class="token punctuation">(</span>img<span class="token punctuation">,</span><span class="token punctuation">(</span><span class="token number">5</span><span class="token punctuation">,</span><span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">,</span><span class="token number">0</span><span class="token punctuation">)</span>
ret3<span class="token punctuation">,</span>th3 <span class="token operator">=</span> cv<span class="token punctuation">.</span>threshold<span class="token punctuation">(</span>blur<span class="token punctuation">,</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token number">255</span><span class="token punctuation">,</span>cv<span class="token punctuation">.</span>THRESH_BINARY<span class="token operator">+</span>cv<span class="token punctuation">.</span>THRESH_OTSU<span class="token punctuation">)</span>

<span class="token comment"># plot all the images and their histograms</span>
images <span class="token operator">=</span> <span class="token punctuation">[</span>img<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> th1<span class="token punctuation">,</span>
          img<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> th2<span class="token punctuation">,</span>
          blur<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> th3<span class="token punctuation">]</span>
titles <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token string">'Original Noisy Image'</span><span class="token punctuation">,</span><span class="token string">'Histogram'</span><span class="token punctuation">,</span><span class="token string">'Global Thresholding (v=127)'</span><span class="token punctuation">,</span>
          <span class="token string">'Original Noisy Image'</span><span class="token punctuation">,</span><span class="token string">'Histogram'</span><span class="token punctuation">,</span><span class="token string">"Otsu's Thresholding"</span><span class="token punctuation">,</span>
          <span class="token string">'Gaussian filtered Image'</span><span class="token punctuation">,</span><span class="token string">'Histogram'</span><span class="token punctuation">,</span><span class="token string">"Otsu's Thresholding"</span><span class="token punctuation">]</span>

<span class="token keyword">for</span> i <span class="token keyword">in</span> <span class="token builtin">xrange</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
    plt<span class="token punctuation">.</span>subplot<span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">,</span><span class="token number">3</span><span class="token punctuation">,</span>i<span class="token operator">*</span><span class="token number">3</span><span class="token operator">+</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">,</span>plt<span class="token punctuation">.</span>imshow<span class="token punctuation">(</span>images<span class="token punctuation">[</span>i<span class="token operator">*</span><span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string">'gray'</span><span class="token punctuation">)</span>
    plt<span class="token punctuation">.</span>title<span class="token punctuation">(</span>titles<span class="token punctuation">[</span>i<span class="token operator">*</span><span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>xticks<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>yticks<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
    plt<span class="token punctuation">.</span>subplot<span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">,</span><span class="token number">3</span><span class="token punctuation">,</span>i<span class="token operator">*</span><span class="token number">3</span><span class="token operator">+</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">,</span>plt<span class="token punctuation">.</span>hist<span class="token punctuation">(</span>images<span class="token punctuation">[</span>i<span class="token operator">*</span><span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">.</span>ravel<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span><span class="token number">256</span><span class="token punctuation">)</span>
    plt<span class="token punctuation">.</span>title<span class="token punctuation">(</span>titles<span class="token punctuation">[</span>i<span class="token operator">*</span><span class="token number">3</span><span class="token operator">+</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>xticks<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>yticks<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
    plt<span class="token punctuation">.</span>subplot<span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">,</span><span class="token number">3</span><span class="token punctuation">,</span>i<span class="token operator">*</span><span class="token number">3</span><span class="token operator">+</span><span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">,</span>plt<span class="token punctuation">.</span>imshow<span class="token punctuation">(</span>images<span class="token punctuation">[</span>i<span class="token operator">*</span><span class="token number">3</span><span class="token operator">+</span><span class="token number">2</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token string">'gray'</span><span class="token punctuation">)</span>
    plt<span class="token punctuation">.</span>title<span class="token punctuation">(</span>titles<span class="token punctuation">[</span>i<span class="token operator">*</span><span class="token number">3</span><span class="token operator">+</span><span class="token number">2</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>xticks<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>yticks<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>show<span class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p><img src="https://cdn.nlark.com/yuque/0/2020/png/448115/1603440178744-7d481550-b13d-4807-a893-26484a332d90.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_13%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#height=346&amp;id=PRl0Y&amp;originHeight=346&amp;originWidth=471&amp;originalType=binary∶=1&amp;size=0&amp;status=done&amp;style=none&amp;width=471" srcset="/img/loading.gif" lazyload alt=""></p>
<h2 id="4-图像形状变换"><a href="#4-图像形状变换" class="headerlink" title="4. 图像形状变换"></a>4. 图像形状变换</h2><h3 id="4-1-cv-resize-图像缩放"><a href="#4-1-cv-resize-图像缩放" class="headerlink" title="4.1 cv.resize()   图像缩放"></a>4.1 cv.resize()   图像缩放</h3><p>缩放是对图像的大小进行调整，即使图像放大或缩小。</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python">cv<span class="token punctuation">.</span>resize<span class="token punctuation">(</span>src<span class="token punctuation">,</span> dsize<span class="token punctuation">,</span> fx<span class="token operator">=</span><span class="token number">0</span><span class="token punctuation">,</span> fy<span class="token operator">=</span><span class="token number">0</span><span class="token punctuation">,</span> interpolation<span class="token operator">=</span>cv2<span class="token punctuation">.</span>INTER_LINEAR<span class="token punctuation">)</span> 放大和缩小图像
    参数：
        src<span class="token punctuation">:</span> 输入图像对象
        dsize：输出矩阵<span class="token operator">/</span>图像的大小，为<span class="token number">0</span>时计算方式如下：dsize <span class="token operator">=</span> Size<span class="token punctuation">(</span><span class="token builtin">round</span><span class="token punctuation">(</span>fx<span class="token operator">*</span>src<span class="token punctuation">.</span>cols<span class="token punctuation">)</span><span class="token punctuation">,</span><span class="token builtin">round</span><span class="token punctuation">(</span>fy<span class="token operator">*</span>src<span class="token punctuation">.</span>rows<span class="token punctuation">)</span><span class="token punctuation">)</span>
        fx<span class="token punctuation">:</span> 水平轴的缩放因子，为<span class="token number">0</span>时计算方式：  <span class="token punctuation">(</span>double<span class="token punctuation">)</span>dsize<span class="token punctuation">.</span>width<span class="token operator">/</span>src<span class="token punctuation">.</span>cols
        fy<span class="token punctuation">:</span> 垂直轴的缩放因子，为<span class="token number">0</span>时计算方式：  <span class="token punctuation">(</span>double<span class="token punctuation">)</span>dsize<span class="token punctuation">.</span>heigh<span class="token operator">/</span>src<span class="token punctuation">.</span>rows
        interpolation：插值算法
            cv<span class="token punctuation">.</span>INTER_NEAREST <span class="token punctuation">:</span> 最近邻插值法
            cv<span class="token punctuation">.</span>INTER_LINEAR   默认值，双线性插值法
            cv<span class="token punctuation">.</span>INTER_AREA        基于局部像素的重采样（resampling using pixel area relation）。对于图像抽取（image decimation）来说，这可能是一个更好的方法。但如果是放大图像时，它和最近邻法的效果类似。
            cv<span class="token punctuation">.</span>INTER_CUBIC        基于4x4像素邻域的<span class="token number">3</span>次插值法
            cv<span class="token punctuation">.</span>INTER_LANCZOS4     基于8x8像素邻域的Lanczos插值

    cv<span class="token punctuation">.</span>INTER_AREA 适合于图像缩小， cv<span class="token punctuation">.</span>INTER_CUBIC <span class="token punctuation">(</span>slow<span class="token punctuation">)</span> <span class="token operator">&amp;</span> cv<span class="token punctuation">.</span>INTER_LINEAR 适合于图像放大<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p>官网示例：</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token keyword">import</span> cv2 <span class="token keyword">as</span> cv
<span class="token keyword">from</span> matplotlib <span class="token keyword">import</span> pyplot <span class="token keyword">as</span> plt

<span class="token comment"># 1. 读取图片</span>
img1 <span class="token operator">=</span> cv<span class="token punctuation">.</span>imread<span class="token punctuation">(</span><span class="token string">"./image/kids.jpg"</span><span class="token punctuation">)</span>
<span class="token comment"># 2.图像缩放</span>
<span class="token comment"># 2.1 绝对尺寸</span>
rows<span class="token punctuation">,</span> cols <span class="token operator">=</span> img1<span class="token punctuation">.</span>shape<span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token number">2</span><span class="token punctuation">]</span>
res <span class="token operator">=</span> cv<span class="token punctuation">.</span>resize<span class="token punctuation">(</span>img1<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token number">2</span> <span class="token operator">*</span> cols<span class="token punctuation">,</span> <span class="token number">2</span> <span class="token operator">*</span> rows<span class="token punctuation">)</span><span class="token punctuation">,</span> interpolation<span class="token operator">=</span>cv<span class="token punctuation">.</span>INTER_CUBIC<span class="token punctuation">)</span>

<span class="token comment"># 2.2 相对尺寸</span>
res1 <span class="token operator">=</span> cv<span class="token punctuation">.</span>resize<span class="token punctuation">(</span>img1<span class="token punctuation">,</span> <span class="token boolean">None</span><span class="token punctuation">,</span> fx<span class="token operator">=</span><span class="token number">0.5</span><span class="token punctuation">,</span> fy<span class="token operator">=</span><span class="token number">0.5</span><span class="token punctuation">)</span>

<span class="token comment"># 3 图像显示</span>
<span class="token comment"># 3.1 使用opencv显示图像(不推荐)</span>
cv<span class="token punctuation">.</span>imshow<span class="token punctuation">(</span><span class="token string">"orignal"</span><span class="token punctuation">,</span> img1<span class="token punctuation">)</span>
cv<span class="token punctuation">.</span>imshow<span class="token punctuation">(</span><span class="token string">"enlarge"</span><span class="token punctuation">,</span> res<span class="token punctuation">)</span>
cv<span class="token punctuation">.</span>imshow<span class="token punctuation">(</span><span class="token string">"shrink）"</span><span class="token punctuation">,</span> res1<span class="token punctuation">)</span>
cv<span class="token punctuation">.</span>waitKey<span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span>

<span class="token comment"># 3.2 使用matplotlib显示图像</span>
fig<span class="token punctuation">,</span> axes <span class="token operator">=</span> plt<span class="token punctuation">.</span>subplots<span class="token punctuation">(</span>nrows<span class="token operator">=</span><span class="token number">1</span><span class="token punctuation">,</span> ncols<span class="token operator">=</span><span class="token number">3</span><span class="token punctuation">,</span> figsize<span class="token operator">=</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">,</span> <span class="token number">8</span><span class="token punctuation">)</span><span class="token punctuation">,</span> dpi<span class="token operator">=</span><span class="token number">100</span><span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>imshow<span class="token punctuation">(</span>res<span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token punctuation">,</span> <span class="token punctuation">:</span><span class="token punctuation">,</span> <span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>set_title<span class="token punctuation">(</span><span class="token string">"绝对尺度（放大）"</span><span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">.</span>imshow<span class="token punctuation">(</span>img1<span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token punctuation">,</span> <span class="token punctuation">:</span><span class="token punctuation">,</span> <span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">.</span>set_title<span class="token punctuation">(</span><span class="token string">"原图"</span><span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">]</span><span class="token punctuation">.</span>imshow<span class="token punctuation">(</span>res1<span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token punctuation">,</span> <span class="token punctuation">:</span><span class="token punctuation">,</span> <span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">]</span><span class="token punctuation">.</span>set_title<span class="token punctuation">(</span><span class="token string">"相对尺度（缩小）"</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>show<span class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617373330704-bd2a29d0-3b8a-4f2c-8140-17248d3bff23.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_29%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png"></p>
<h3 id="4-2-cv-warpAffine-仿射变换"><a href="#4-2-cv-warpAffine-仿射变换" class="headerlink" title="4.2 cv.warpAffine()      仿射变换"></a>4.2 cv.warpAffine()      仿射变换</h3><p>仿射变换（从二维坐标到二维坐标之间的线性变换，且保持二维图形的“平直性”和“平行性”。仿射变换可以通过一系列的原子变换的复合来实现，包括平移，缩放，翻转，旋转和剪切）</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python">cv<span class="token punctuation">.</span>warpAffine<span class="token punctuation">(</span><span class="token punctuation">)</span>   仿射变换（从二维坐标到二维坐标之间的线性变换，且保持二维图形的“平直性”和“平行性”。仿射变换可以通过一系列的原子变换的复合来实现，包括平移，缩放，翻转，旋转和剪切）
    参数：
        img<span class="token punctuation">:</span> 图像对象
        M：<span class="token number">2</span><span class="token operator">*</span><span class="token number">3</span> transformation matrix <span class="token punctuation">(</span>转变矩阵<span class="token punctuation">)</span>
        dsize：输出矩阵的大小<span class="token punctuation">,</span>注意格式为（cols，rows）  即width对应cols，height对应rows
        flags：可选，插值算法标识符，有默认值INTER_LINEAR，
               如果插值算法为WARP_INVERSE_MAP<span class="token punctuation">,</span> warpAffine函数使用如下矩阵进行图像转dst<span class="token punctuation">(</span>x<span class="token punctuation">,</span>y<span class="token punctuation">)</span><span class="token operator">=</span>src<span class="token punctuation">(</span>M11<span class="token operator">*</span>x<span class="token operator">+</span>M12<span class="token operator">*</span>y<span class="token operator">+</span>M13<span class="token punctuation">,</span>M21<span class="token operator">*</span>x<span class="token operator">+</span>M22<span class="token operator">*</span>y<span class="token operator">+</span>M23<span class="token punctuation">)</span>
        borderMode：可选， 边界像素模式，有默认值BORDER_CONSTANT
        borderValue<span class="token punctuation">:</span>可选，边界取值，有默认值Scalar<span class="token punctuation">(</span><span class="token punctuation">)</span>即<span class="token number">0</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p>常用插值算法：<br><img src="https://cdn.nlark.com/yuque/0/2020/png/448115/1603440178823-96afaa0d-b385-4556-bc9b-0df72a2ff033.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_16%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#height=352&amp;id=pii0x&amp;originHeight=352&amp;originWidth=573&amp;originalType=binary∶=1&amp;size=0&amp;status=done&amp;style=none&amp;width=573" srcset="/img/loading.gif" lazyload alt=""><br>仿射变换的本质：即一个矩阵 A 和向量 B 共同组成的转变矩阵，和原图像坐标相乘来得到新图像的坐标，从而实现图像移动，旋转等。如下矩阵 A 和向量 B 组成的转变矩阵 M，用来对原图像的坐标（x,y）进行转变，得到新坐标向量 T<br>矩阵 A 和向量 B<br><img src="https://cdn.nlark.com/yuque/0/2020/png/448115/1603440178765-a34f69bf-11b8-4ac1-a264-9e917c835dd1.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_15%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#height=114&amp;id=pU6QE&amp;originHeight=114&amp;originWidth=330&amp;originalType=binary∶=1&amp;size=0&amp;status=done&amp;style=none&amp;width=330" srcset="/img/loading.gif" lazyload alt=""><br>仿射变换（矩阵计算）：变换前坐标（x,y）<br><img src="https://cdn.nlark.com/yuque/0/2020/png/448115/1603440178759-f415d73a-be00-49f5-8331-30fc25003d01.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_13%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#height=85&amp;id=UCeET&amp;originHeight=85&amp;originWidth=296&amp;originalType=binary∶=1&amp;size=0&amp;status=done&amp;style=none&amp;width=296" srcset="/img/loading.gif" lazyload alt=""><br>变换结果：变换后坐标（a00<em>x+a01 </em>y+b00, a10<em>x+a11</em>y+b10）<br><img src="https://cdn.nlark.com/yuque/0/2020/png/448115/1603440178760-e43ede53-fd59-4244-bc2a-536c394482b9.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_9%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#height=64&amp;id=zf3dA&amp;originHeight=64&amp;originWidth=209&amp;originalType=binary∶=1&amp;size=0&amp;status=done&amp;style=none&amp;width=209" srcset="/img/loading.gif" lazyload alt=""></p>
<h4 id="4-2-1-平移变换"><a href="#4-2-1-平移变换" class="headerlink" title="4.2.1 平移变换"></a>4.2.1 平移变换</h4><p>了解了仿射变换的概念，平移变换只是采用了一个如下的转变矩阵（transformation matrix）: 从（x,y）平移到（x+tx, y+ty）<br>　　　　　　　　　　　　　　　　　　<img src="https://cdn.nlark.com/yuque/0/2020/png/448115/1603440178720-f53e78b9-3241-45ad-b4f0-ebc840a4b696.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_9%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#height=63&amp;id=YtGQ9&amp;originHeight=63&amp;originWidth=159&amp;originalType=binary∶=1&amp;size=0&amp;status=done&amp;style=none&amp;width=159" srcset="/img/loading.gif" lazyload alt=""><br>　　　　　　　　　　　<img src="https://cdn.nlark.com/yuque/0/2020/png/448115/1603440178814-da807751-1cb6-4f96-968f-a195d73c1a34.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_12%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#height=102&amp;id=yWjN7&amp;originHeight=102&amp;originWidth=432&amp;originalType=binary∶=1&amp;size=0&amp;status=done&amp;style=none&amp;width=432" srcset="/img/loading.gif" lazyload alt=""><br>官网使用示例：向左平移 100，向下平移 50</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python">cv<span class="token punctuation">.</span>warpAffine<span class="token punctuation">(</span>img<span class="token punctuation">,</span> M<span class="token punctuation">,</span> dsize<span class="token punctuation">)</span>
    img<span class="token punctuation">:</span> 输入图像
    M： <span class="token number">2</span><span class="token operator">*</span>∗<span class="token number">3</span>移动矩阵
    dsize<span class="token punctuation">:</span> 输出图像的大小<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span></span></code></pre></div>
<p><strong>注意：输出图像的大小，它应该是(宽度，高度)的形式。请记住,width=列数，height=行数</strong></p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token keyword">import</span> numpy <span class="token keyword">as</span> np
<span class="token keyword">import</span> cv2 <span class="token keyword">as</span> cv
<span class="token keyword">import</span> matplotlib<span class="token punctuation">.</span>pyplot <span class="token keyword">as</span> plt

<span class="token comment"># 1. 读取图像</span>
img1 <span class="token operator">=</span> cv<span class="token punctuation">.</span>imread<span class="token punctuation">(</span><span class="token string">"./image/kids.jpg"</span><span class="token punctuation">)</span>

<span class="token comment"># 2. 图像平移</span>
rows<span class="token punctuation">,</span> cols <span class="token operator">=</span> img1<span class="token punctuation">.</span>shape<span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token number">2</span><span class="token punctuation">]</span>
M <span class="token operator">=</span> M <span class="token operator">=</span> np<span class="token punctuation">.</span>float32<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">100</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">50</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">)</span>  <span class="token comment"># 平移矩阵</span>
dst <span class="token operator">=</span> cv<span class="token punctuation">.</span>warpAffine<span class="token punctuation">(</span>img1<span class="token punctuation">,</span> M<span class="token punctuation">,</span> <span class="token punctuation">(</span>cols<span class="token punctuation">,</span> rows<span class="token punctuation">)</span><span class="token punctuation">)</span>

<span class="token comment"># 3. 图像显示</span>
fig<span class="token punctuation">,</span> axes <span class="token operator">=</span> plt<span class="token punctuation">.</span>subplots<span class="token punctuation">(</span>nrows<span class="token operator">=</span><span class="token number">1</span><span class="token punctuation">,</span> ncols<span class="token operator">=</span><span class="token number">2</span><span class="token punctuation">,</span> figsize<span class="token operator">=</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">,</span> <span class="token number">8</span><span class="token punctuation">)</span><span class="token punctuation">,</span> dpi<span class="token operator">=</span><span class="token number">100</span><span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>imshow<span class="token punctuation">(</span>img1<span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token punctuation">,</span> <span class="token punctuation">:</span><span class="token punctuation">,</span> <span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>set_title<span class="token punctuation">(</span><span class="token string">"原图"</span><span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">.</span>imshow<span class="token punctuation">(</span>dst<span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token punctuation">,</span> <span class="token punctuation">:</span><span class="token punctuation">,</span> <span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">.</span>set_title<span class="token punctuation">(</span><span class="token string">"平移后结果"</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>show<span class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617373487855-b1437839-ef57-4731-a063-f1898447b55a.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_20%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png"></p>
<h4 id="4-2-2-放大和缩小"><a href="#4-2-2-放大和缩小" class="headerlink" title="4.2.2 放大和缩小"></a>4.2.2 放大和缩小</h4><p>放大和缩小指相对于原坐标（x,y）,变换为了（a<em>x, b</em>y）,即水平方向放大了 a 倍，水平方向放大了 b 倍，其对应的转变矩阵如下：<br>　　　<img src="https://cdn.nlark.com/yuque/0/2020/png/448115/1603440178832-6c6e20b7-9366-426b-87a7-8e1fe5917a66.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_12%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#height=124&amp;id=HLuiw&amp;originHeight=124&amp;originWidth=409&amp;originalType=binary∶=1&amp;size=0&amp;status=done&amp;style=none&amp;width=409" srcset="/img/loading.gif" lazyload alt=""></p>
<h4 id="4-2-3-旋转变换"><a href="#4-2-3-旋转变换" class="headerlink" title="4.2.3 旋转变换"></a>4.2.3 旋转变换</h4><p><strong>图像旋转是指图像按照某个位置转动一定角度的过程，旋转中图像仍保持这原始尺寸。图像旋转后图像的水平对称轴、垂直对称轴及中心坐标原点都可能会发生变换，因此需要对图像旋转中的坐标进行相应转换。</strong><br>将（x,y），以坐标原点为中心，顺时针方向旋转 α 得到(x1,y1)， 有如下关系 x1 = xcosα-ysinα, y1 =xsinα+ycosα; 因此可以构建对应的转变矩阵如下：<img src="https://cdn.nlark.com/yuque/0/2020/png/448115/1603440178751-bd7a8973-d495-4146-b0ac-e68ea9a54113.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_10%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#height=73&amp;id=ZikP8&amp;originHeight=73&amp;originWidth=214&amp;originalType=binary∶=1&amp;size=0&amp;status=done&amp;style=none&amp;width=214" srcset="/img/loading.gif" lazyload alt=""><br>opencv 将其扩展到，任意点 center 为中心进行顺时针旋转 α，放大 scale 倍的，转变矩阵如下：<br>　　　　　　　　　　　　<img src="https://cdn.nlark.com/yuque/0/2020/png/448115/1603440178794-884b148f-b8c3-4278-9471-917b9258aa48.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_12%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#height=146&amp;id=P6cFP&amp;originHeight=146&amp;originWidth=405&amp;originalType=binary∶=1&amp;size=0&amp;status=done&amp;style=none&amp;width=405" srcset="/img/loading.gif" lazyload alt=""><br>通过 getRotationMatrix2D()能得到转变矩阵</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python">cv<span class="token punctuation">.</span>getRotationMatrix2D<span class="token punctuation">(</span><span class="token punctuation">)</span>  返回<span class="token number">2</span><span class="token operator">*</span><span class="token number">3</span>的转变矩阵（浮点型）
    参数：
        center：旋转的中心点坐标
        angle：旋转角度，单位为度数，证书表示逆时针旋转
        scale：同方向的放大倍数<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token keyword">import</span> numpy <span class="token keyword">as</span> np
<span class="token keyword">import</span> cv2 <span class="token keyword">as</span> cv
<span class="token keyword">import</span> matplotlib<span class="token punctuation">.</span>pyplot <span class="token keyword">as</span> plt

<span class="token comment"># 1 读取图像</span>
img <span class="token operator">=</span> cv<span class="token punctuation">.</span>imread<span class="token punctuation">(</span><span class="token string">"./image/kids.jpg"</span><span class="token punctuation">)</span>

<span class="token comment"># 2 图像旋转</span>
rows<span class="token punctuation">,</span> cols <span class="token operator">=</span> img<span class="token punctuation">.</span>shape<span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token number">2</span><span class="token punctuation">]</span>
<span class="token comment"># 2.1 生成旋转矩阵</span>
M <span class="token operator">=</span> cv<span class="token punctuation">.</span>getRotationMatrix2D<span class="token punctuation">(</span><span class="token punctuation">(</span>cols <span class="token operator">/</span> <span class="token number">2</span><span class="token punctuation">,</span> rows <span class="token operator">/</span> <span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token number">90</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span>
<span class="token comment"># 2.2 进行旋转变换</span>
dst <span class="token operator">=</span> cv<span class="token punctuation">.</span>warpAffine<span class="token punctuation">(</span>img<span class="token punctuation">,</span> M<span class="token punctuation">,</span> <span class="token punctuation">(</span>cols<span class="token punctuation">,</span> rows<span class="token punctuation">)</span><span class="token punctuation">)</span>

<span class="token comment"># 3 图像展示</span>
fig<span class="token punctuation">,</span> axes <span class="token operator">=</span> plt<span class="token punctuation">.</span>subplots<span class="token punctuation">(</span>nrows<span class="token operator">=</span><span class="token number">1</span><span class="token punctuation">,</span> ncols<span class="token operator">=</span><span class="token number">2</span><span class="token punctuation">,</span> figsize<span class="token operator">=</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">,</span> <span class="token number">8</span><span class="token punctuation">)</span><span class="token punctuation">,</span> dpi<span class="token operator">=</span><span class="token number">100</span><span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>imshow<span class="token punctuation">(</span>img<span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token punctuation">,</span> <span class="token punctuation">:</span><span class="token punctuation">,</span> <span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>set_title<span class="token punctuation">(</span><span class="token string">"原图"</span><span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">.</span>imshow<span class="token punctuation">(</span>dst<span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token punctuation">,</span> <span class="token punctuation">:</span><span class="token punctuation">,</span> <span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">.</span>set_title<span class="token punctuation">(</span><span class="token string">"旋转后结果"</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>show<span class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617373576429-c1a9326c-56f3-4ab4-9dcb-e0f37e1e18b5.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_21%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png"></p>
<h4 id="4-2-4-仿射变换矩阵的计算"><a href="#4-2-4-仿射变换矩阵的计算" class="headerlink" title="4.2.4 仿射变换矩阵的计算"></a>4.2.4 仿射变换矩阵的计算</h4><p>通过上述的平移，缩放，旋转的组合变换即实现了仿射变换，上述多个变换的变换矩阵相乘即能得到组合变换的变换矩阵。同时该变换矩阵中涉及到六个未知数（2*3 的矩阵），通过变换前后对应三组坐标，也可以求出变换矩阵，opencv 提供了函数 getAffineTransform()来计算变化矩阵</p>
<ol>
<li>矩阵相乘：将平移，旋转和缩放的变换矩阵相乘，最后即为仿射变换矩阵</li>
<li>getAffineTransform()：根据变换前后三组坐标计算变换矩阵</li>
</ol>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python">cv<span class="token punctuation">.</span>getAffineTransform<span class="token punctuation">(</span><span class="token punctuation">)</span>  返回<span class="token number">2</span><span class="token operator">*</span><span class="token number">3</span>的转变矩阵
    参数：
        src：原图像中的三组坐标，如np<span class="token punctuation">.</span>float32<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token number">50</span><span class="token punctuation">,</span><span class="token number">50</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token punctuation">[</span><span class="token number">200</span><span class="token punctuation">,</span><span class="token number">50</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token punctuation">[</span><span class="token number">50</span><span class="token punctuation">,</span><span class="token number">200</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
        dst<span class="token punctuation">:</span> 转换后的对应三组坐标，如np<span class="token punctuation">.</span>float32<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token number">10</span><span class="token punctuation">,</span><span class="token number">100</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token punctuation">[</span><span class="token number">200</span><span class="token punctuation">,</span><span class="token number">50</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token punctuation">[</span><span class="token number">100</span><span class="token punctuation">,</span><span class="token number">250</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span></span></code></pre></div>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token keyword">import</span> numpy <span class="token keyword">as</span> np
<span class="token keyword">import</span> cv2 <span class="token keyword">as</span> cv
<span class="token keyword">import</span> matplotlib<span class="token punctuation">.</span>pyplot <span class="token keyword">as</span> plt

<span class="token comment"># 1 图像读取</span>
img <span class="token operator">=</span> cv<span class="token punctuation">.</span>imread<span class="token punctuation">(</span><span class="token string">"./image/kids.jpg"</span><span class="token punctuation">)</span>

<span class="token comment"># 2 仿射变换</span>
rows<span class="token punctuation">,</span> cols <span class="token operator">=</span> img<span class="token punctuation">.</span>shape<span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token number">2</span><span class="token punctuation">]</span>
<span class="token comment"># 2.1 创建变换矩阵</span>
pts1 <span class="token operator">=</span> np<span class="token punctuation">.</span>float32<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token number">50</span><span class="token punctuation">,</span> <span class="token number">50</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token number">200</span><span class="token punctuation">,</span> <span class="token number">50</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token number">50</span><span class="token punctuation">,</span> <span class="token number">200</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
pts2 <span class="token operator">=</span> np<span class="token punctuation">.</span>float32<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token number">100</span><span class="token punctuation">,</span> <span class="token number">100</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token number">200</span><span class="token punctuation">,</span> <span class="token number">50</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token number">100</span><span class="token punctuation">,</span> <span class="token number">250</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
M <span class="token operator">=</span> cv<span class="token punctuation">.</span>getAffineTransform<span class="token punctuation">(</span>pts1<span class="token punctuation">,</span> pts2<span class="token punctuation">)</span>
<span class="token comment"># 2.2 完成仿射变换</span>
dst <span class="token operator">=</span> cv<span class="token punctuation">.</span>warpAffine<span class="token punctuation">(</span>img<span class="token punctuation">,</span> M<span class="token punctuation">,</span> <span class="token punctuation">(</span>cols<span class="token punctuation">,</span> rows<span class="token punctuation">)</span><span class="token punctuation">)</span>

<span class="token comment"># 3 图像显示</span>
fig<span class="token punctuation">,</span> axes <span class="token operator">=</span> plt<span class="token punctuation">.</span>subplots<span class="token punctuation">(</span>nrows<span class="token operator">=</span><span class="token number">1</span><span class="token punctuation">,</span> ncols<span class="token operator">=</span><span class="token number">2</span><span class="token punctuation">,</span> figsize<span class="token operator">=</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">,</span> <span class="token number">8</span><span class="token punctuation">)</span><span class="token punctuation">,</span> dpi<span class="token operator">=</span><span class="token number">100</span><span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>imshow<span class="token punctuation">(</span>img<span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token punctuation">,</span> <span class="token punctuation">:</span><span class="token punctuation">,</span> <span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>set_title<span class="token punctuation">(</span><span class="token string">"原图"</span><span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">.</span>imshow<span class="token punctuation">(</span>dst<span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token punctuation">,</span> <span class="token punctuation">:</span><span class="token punctuation">,</span> <span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">.</span>set_title<span class="token punctuation">(</span><span class="token string">"仿射后结果"</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>show<span class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617373620628-4ba09de1-c440-4899-a033-84c9de766402.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_23%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png"></p>
<h3 id="4-3-透视变换-persperctive-transformation"><a href="#4-3-透视变换-persperctive-transformation" class="headerlink" title="4.3 透视变换(persperctive transformation)"></a>4.3 透视变换(persperctive transformation)</h3><p>仿射变换都是在二维空间的变换，透视变换（投影变换）是在三维空间中发生了旋转。需要前后四组坐标来计算对应的转变矩阵，opencv 提供了函数 getPerspectiveTransform()来计算转变矩阵，cv2.wrapPerspective()函数来进行透视变换。其对应参数如下：</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python">cv<span class="token punctuation">.</span>getPerspectiveTransform<span class="token punctuation">(</span><span class="token punctuation">)</span>   返回<span class="token number">3</span><span class="token operator">*</span><span class="token number">3</span>的转变矩阵
    src：原图像中的四组坐标，如 np<span class="token punctuation">.</span>float32<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token number">56</span><span class="token punctuation">,</span><span class="token number">65</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token punctuation">[</span><span class="token number">368</span><span class="token punctuation">,</span><span class="token number">52</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token punctuation">[</span><span class="token number">28</span><span class="token punctuation">,</span><span class="token number">387</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token punctuation">[</span><span class="token number">389</span><span class="token punctuation">,</span><span class="token number">390</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
    dst<span class="token punctuation">:</span> 转换后的对应四组坐标，如np<span class="token punctuation">.</span>float32<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token punctuation">[</span><span class="token number">300</span><span class="token punctuation">,</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token number">300</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token punctuation">[</span><span class="token number">300</span><span class="token punctuation">,</span><span class="token number">300</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">)</span>

cv<span class="token punctuation">.</span>wrapPerspective<span class="token punctuation">(</span><span class="token punctuation">)</span>
	src<span class="token punctuation">:</span> 图像对象
    M：<span class="token number">3</span><span class="token operator">*</span><span class="token number">3</span> transformation matrix <span class="token punctuation">(</span>转变矩阵<span class="token punctuation">)</span>
    dsize：输出矩阵的大小，注意格式为（cols，rows）  即width对应cols，height对应rows
    flags：可选，插值算法标识符，有默认值INTER_LINEAR，如果插值算法为WARP_INVERSE_MAP<span class="token punctuation">,</span> warpAffine函数使用如下矩阵进行图像转dst<span class="token punctuation">(</span>x<span class="token punctuation">,</span>y<span class="token punctuation">)</span><span class="token operator">=</span>src<span class="token punctuation">(</span>M11<span class="token operator">*</span>x<span class="token operator">+</span>M12<span class="token operator">*</span>y<span class="token operator">+</span>M13<span class="token punctuation">,</span>M21<span class="token operator">*</span>x<span class="token operator">+</span>M22<span class="token operator">*</span>y<span class="token operator">+</span>M23<span class="token punctuation">)</span>
    borderMode：可选， 边界像素模式，有默认值BORDER_CONSTANT
    borderValue<span class="token punctuation">:</span>可选，边界取值，有默认值Scalar<span class="token punctuation">(</span><span class="token punctuation">)</span>即<span class="token number">0</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p>使用示例：</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token keyword">import</span> cv2 <span class="token keyword">as</span> cv
<span class="token keyword">import</span> numpy <span class="token keyword">as</span> np
<span class="token comment"># 1 读取图像</span>

img <span class="token operator">=</span> cv<span class="token punctuation">.</span>imread<span class="token punctuation">(</span><span class="token string">"./image/poker.jpg"</span><span class="token punctuation">)</span>

width<span class="token punctuation">,</span> height <span class="token operator">=</span> <span class="token number">250</span><span class="token punctuation">,</span> <span class="token number">350</span>
<span class="token comment"># 2 创建变换矩阵</span>
<span class="token comment"># 找到扑克牌中的四个点</span>
pts1 <span class="token operator">=</span> np<span class="token punctuation">.</span>float32<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token number">111</span><span class="token punctuation">,</span> <span class="token number">219</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token punctuation">[</span><span class="token number">287</span><span class="token punctuation">,</span> <span class="token number">188</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token punctuation">[</span><span class="token number">154</span><span class="token punctuation">,</span> <span class="token number">482</span><span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token punctuation">[</span><span class="token number">352</span><span class="token punctuation">,</span> <span class="token number">440</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
pts2 <span class="token operator">=</span> np<span class="token punctuation">.</span>float32<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">[</span>width<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">,</span> height<span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">[</span>width<span class="token punctuation">,</span> height<span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
matrix <span class="token operator">=</span> cv<span class="token punctuation">.</span>getPerspectiveTransform<span class="token punctuation">(</span>pts1<span class="token punctuation">,</span> pts2<span class="token punctuation">)</span>
<span class="token comment"># 3 进行变换</span>
imgOutput <span class="token operator">=</span> cv<span class="token punctuation">.</span>warpPerspective<span class="token punctuation">(</span>img<span class="token punctuation">,</span> matrix<span class="token punctuation">,</span> <span class="token punctuation">(</span>width<span class="token punctuation">,</span> height<span class="token punctuation">)</span><span class="token punctuation">)</span>

<span class="token comment"># 4 图像显示</span>
cv<span class="token punctuation">.</span>imshow<span class="token punctuation">(</span><span class="token string">"Image"</span><span class="token punctuation">,</span> img<span class="token punctuation">)</span>
cv<span class="token punctuation">.</span>imshow<span class="token punctuation">(</span><span class="token string">"Output"</span><span class="token punctuation">,</span> imgOutput<span class="token punctuation">)</span>

cv<span class="token punctuation">.</span>waitKey<span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p><img src="https://cdn.nlark.com/yuque/0/2020/png/448115/1603448225125-72b2c7aa-30e9-4b45-985e-8dd593ce62f7.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_27%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png">从上图中可以透视变换的一个应用，如果能找到原图中纸张的四个顶点，将其转换到新图中纸张的四个顶点，能将歪斜的 roi 区域转正，并进行放大；如在书籍，名片拍照上传后进行识别时，是一个很好的图片预处理方法。</p>
<h2 id="5-形态学操作"><a href="#5-形态学操作" class="headerlink" title="5. 形态学操作"></a>5. 形态学操作</h2><p>形态学转换是基于图像形状的一些简单操作。它通常在二进制图像上执行。腐蚀和膨胀是两个基本的形态学运算符。然后它的变体形式如开运算，闭运算，礼帽黑帽等。</p>
<h3 id="5-1-腐蚀和膨胀"><a href="#5-1-腐蚀和膨胀" class="headerlink" title="5.1 腐蚀和膨胀"></a>5.1 腐蚀和膨胀</h3><p>腐蚀和膨胀是最基本的形态学操作，腐蚀和膨胀都是针对白色部分（高亮部分）而言的。<br>膨胀就是使图像中高亮部分扩张，效果图拥有比原图更大的高亮区域；腐蚀是原图中的高亮区域被蚕食，效果图拥有比原图更小的高亮区域。膨胀是求局部最大值的操作，腐蚀是求局部最小值的操作。</p>
<ol>
<li><strong>腐蚀</strong><br>具体操作是：用一个结构元素扫描图像中的每一个像素，用结构元素中的每一个像素与其覆盖的像素做“与”操作，如果都为 1，则该像素为 1，否则为 0。如下图所示，结构 A 被结构 B 腐蚀后：</li>
</ol>
<p><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617374948515-3a42045d-2d3c-4401-b092-0d602caeab02.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_20%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png"></p>
<h6 id="腐蚀的作用是消除物体边界点，使目标缩小，可以消除小于结构元素的噪声点。"><a href="#腐蚀的作用是消除物体边界点，使目标缩小，可以消除小于结构元素的噪声点。" class="headerlink" title="腐蚀的作用是消除物体边界点，使目标缩小，可以消除小于结构元素的噪声点。"></a>腐蚀的<strong>作用</strong>是消除物体边界点，使目标缩小，可以消除小于结构元素的噪声点。</h6><p><strong>API</strong>：</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python">cv<span class="token punctuation">.</span>erode<span class="token punctuation">(</span>img<span class="token punctuation">,</span>kernel<span class="token punctuation">,</span>iterations<span class="token punctuation">)</span>
    img<span class="token punctuation">:</span> 要处理的图像
    kernel<span class="token punctuation">:</span> 核结构
    iterations<span class="token punctuation">:</span> 腐蚀的次数，默认是<span class="token number">1</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span></span></code></pre></div>
<ol>
<li><strong>膨胀</strong></li>
</ol>
<p>具体操作是：用一个结构元素扫描图像中的每一个像素，用结构元素中的每一个像素与其覆盖的像素做“与”操作，如果都为 0，则该像素为 0，否则为 1。如下图所示，结构 A 被结构 B 腐蚀后：<img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617374931837-0282dca4-6743-42cd-9d00-b0ad2bacbfa3.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_21%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#height=274&amp;id=M9MMf&amp;margin=%5Bobject%20Object%5D&amp;name=image.png&amp;originHeight=274&amp;originWidth=720&amp;originalType=binary∶=1&amp;size=32674&amp;status=done&amp;style=none&amp;width=720" srcset="/img/loading.gif" lazyload alt="image.png"></p>
<h6 id="膨胀的作用是将与物体接触的所有背景点合并到物体中，使目标增大，可添补目标中的孔洞。"><a href="#膨胀的作用是将与物体接触的所有背景点合并到物体中，使目标增大，可添补目标中的孔洞。" class="headerlink" title="膨胀的作用是将与物体接触的所有背景点合并到物体中，使目标增大，可添补目标中的孔洞。"></a>膨胀的作用是将与物体接触的所有背景点合并到物体中，使目标增大，可添补目标中的孔洞。</h6><p><strong>API</strong>：</p>
<div class="code-wrapper"><pre class="line-numbers language-none"><code class="language-none">cv.dilate(img,kernel,iterations)
  img: 要处理的图像
  kernel: 核结构
  iterations: 腐蚀的次数，默认是1<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span></span></code></pre></div>
<ol>
<li><strong>示例</strong></li>
</ol>
<p>我们使用一个 5*5 的卷积核实现腐蚀和膨胀的运算：</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token keyword">import</span> numpy <span class="token keyword">as</span> np
<span class="token keyword">import</span> cv2 <span class="token keyword">as</span> cv
<span class="token keyword">import</span> matplotlib<span class="token punctuation">.</span>pyplot <span class="token keyword">as</span> plt

<span class="token comment"># 1 读取图像</span>
img <span class="token operator">=</span> cv<span class="token punctuation">.</span>imread<span class="token punctuation">(</span><span class="token string">"./image/letter.png"</span><span class="token punctuation">)</span>
<span class="token comment"># 2 创建核结构</span>
kernel <span class="token operator">=</span> np<span class="token punctuation">.</span>ones<span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">,</span> np<span class="token punctuation">.</span>uint8<span class="token punctuation">)</span>

<span class="token comment"># 3 图像腐蚀和膨胀</span>
erosion <span class="token operator">=</span> cv<span class="token punctuation">.</span>erode<span class="token punctuation">(</span>img<span class="token punctuation">,</span> kernel<span class="token punctuation">)</span>  <span class="token comment"># 腐蚀</span>
dilate <span class="token operator">=</span> cv<span class="token punctuation">.</span>dilate<span class="token punctuation">(</span>img<span class="token punctuation">,</span> kernel<span class="token punctuation">)</span>  <span class="token comment"># 膨胀</span>

<span class="token comment"># 4 图像展示</span>
fig<span class="token punctuation">,</span> axes <span class="token operator">=</span> plt<span class="token punctuation">.</span>subplots<span class="token punctuation">(</span>nrows<span class="token operator">=</span><span class="token number">1</span><span class="token punctuation">,</span> ncols<span class="token operator">=</span><span class="token number">3</span><span class="token punctuation">,</span> figsize<span class="token operator">=</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">,</span> <span class="token number">8</span><span class="token punctuation">)</span><span class="token punctuation">,</span> dpi<span class="token operator">=</span><span class="token number">100</span><span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>imshow<span class="token punctuation">(</span>img<span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>set_title<span class="token punctuation">(</span><span class="token string">"原图"</span><span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">.</span>imshow<span class="token punctuation">(</span>erosion<span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">.</span>set_title<span class="token punctuation">(</span><span class="token string">"腐蚀后结果"</span><span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">]</span><span class="token punctuation">.</span>imshow<span class="token punctuation">(</span>dilate<span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">]</span><span class="token punctuation">.</span>set_title<span class="token punctuation">(</span><span class="token string">"膨胀后结果"</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>show<span class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617374915472-40958e3a-1812-4d57-be20-e0a1a5ddd6e7.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_23%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png"></p>
<h3 id="5-2-开闭运算"><a href="#5-2-开闭运算" class="headerlink" title="5.2 开闭运算"></a>5.2 开闭运算</h3><p>开运算和闭运算是将腐蚀和膨胀按照一定的次序进行处理。 但这两者并不是可逆的，即先开后闭并不能得到原来的图像。</p>
<ol>
<li><strong>开运算</strong><br>开运算是先腐蚀后膨胀，其<strong>作用</strong>是：分离物体，消除小区域。<strong>特点</strong>：消除噪点，去除小的干扰块，而不影响原来的图像。<br><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617374906407-98a10cac-cee2-458e-baf9-896895dd8513.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_21%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#height=467&amp;id=s3InA&amp;margin=%5Bobject%20Object%5D&amp;name=image.png&amp;originHeight=467&amp;originWidth=729&amp;originalType=binary∶=1&amp;size=86120&amp;status=done&amp;style=none&amp;width=729" srcset="/img/loading.gif" lazyload alt="image.png"></li>
<li><strong>闭运算</strong><br>闭运算与开运算相反，是先膨胀后腐蚀，<strong>作用</strong>是消除/“闭合”物体里面的孔洞，<strong>特点</strong>：可以填充闭合区域。</li>
</ol>
<p><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617374899714-983e6827-bf2d-4886-bfa6-402832bc82f2.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_21%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png"></p>
<ol>
<li><strong>API</strong></li>
</ol>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python">cv<span class="token punctuation">.</span>morphologyEx<span class="token punctuation">(</span>img<span class="token punctuation">,</span> op<span class="token punctuation">,</span> kernel<span class="token punctuation">)</span>
    img<span class="token punctuation">:</span> 要处理的图像
    op<span class="token punctuation">:</span> 处理方式：若进行开运算，则设为cv<span class="token punctuation">.</span>MORPH_OPEN，若进行闭运算，则设为cv<span class="token punctuation">.</span>MORPH_CLOSE
    Kernel： 核结构<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span></span></code></pre></div>
<ol>
<li><strong>示例</strong><br>使用 10*10 的核结构对卷积进行开闭运算的实现。</li>
</ol>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token keyword">import</span> numpy <span class="token keyword">as</span> np
<span class="token keyword">import</span> cv2 <span class="token keyword">as</span> cv
<span class="token keyword">import</span> matplotlib<span class="token punctuation">.</span>pyplot <span class="token keyword">as</span> plt

<span class="token comment"># 1 读取图像</span>
img1 <span class="token operator">=</span> cv<span class="token punctuation">.</span>imread<span class="token punctuation">(</span><span class="token string">"./image/letter1.png"</span><span class="token punctuation">)</span>
img2 <span class="token operator">=</span> cv<span class="token punctuation">.</span>imread<span class="token punctuation">(</span><span class="token string">"./image/letter2.png"</span><span class="token punctuation">)</span>
<span class="token comment"># 2 创建核结构</span>
kernel <span class="token operator">=</span> np<span class="token punctuation">.</span>ones<span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">,</span> np<span class="token punctuation">.</span>uint8<span class="token punctuation">)</span>
<span class="token comment"># 3 图像的开闭运算</span>
cvOpen <span class="token operator">=</span> cv<span class="token punctuation">.</span>morphologyEx<span class="token punctuation">(</span>img1<span class="token punctuation">,</span> cv<span class="token punctuation">.</span>MORPH_OPEN<span class="token punctuation">,</span> kernel<span class="token punctuation">)</span>  <span class="token comment"># 开运算</span>
cvClose <span class="token operator">=</span> cv<span class="token punctuation">.</span>morphologyEx<span class="token punctuation">(</span>img2<span class="token punctuation">,</span> cv<span class="token punctuation">.</span>MORPH_CLOSE<span class="token punctuation">,</span> kernel<span class="token punctuation">)</span>  <span class="token comment"># 闭运算</span>
<span class="token comment"># 4 图像展示</span>
fig<span class="token punctuation">,</span> axes <span class="token operator">=</span> plt<span class="token punctuation">.</span>subplots<span class="token punctuation">(</span>nrows<span class="token operator">=</span><span class="token number">2</span><span class="token punctuation">,</span> ncols<span class="token operator">=</span><span class="token number">2</span><span class="token punctuation">,</span> figsize<span class="token operator">=</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">,</span> <span class="token number">8</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>imshow<span class="token punctuation">(</span>img1<span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>set_title<span class="token punctuation">(</span><span class="token string">"原图"</span><span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">.</span>imshow<span class="token punctuation">(</span>cvOpen<span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">.</span>set_title<span class="token punctuation">(</span><span class="token string">"开运算结果"</span><span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>imshow<span class="token punctuation">(</span>img2<span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>set_title<span class="token punctuation">(</span><span class="token string">"原图"</span><span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">.</span>imshow<span class="token punctuation">(</span>cvClose<span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">.</span>set_title<span class="token punctuation">(</span><span class="token string">"闭运算结果"</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>show<span class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617374873761-0ab46f02-d306-42b9-bf8e-10dca2cacf6b.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_21%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png"></p>
<h3 id="5-3-礼帽和黑帽"><a href="#5-3-礼帽和黑帽" class="headerlink" title="5.3 礼帽和黑帽"></a>5.3 礼帽和黑帽</h3><ol>
<li><strong>礼帽运算</strong><br>原图像与“开运算“的结果图之差，如下式计算：<br><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617374862119-8c27ef5b-4be8-43e7-881d-f960797865d1.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_21%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#height=36&amp;id=ee0ev&amp;margin=%5Bobject%20Object%5D&amp;name=image.png&amp;originHeight=36&amp;originWidth=730&amp;originalType=binary∶=1&amp;size=41420&amp;status=done&amp;style=none&amp;width=730" srcset="/img/loading.gif" lazyload alt="image.png"><br>　　因为开运算带来的结果是放大了裂缝或者局部低亮度的区域，因此，从原图中减去开运算后的图，得到的效果图突出了比原图轮廓周围的区域更明亮的区域，且这一操作和选择的核的大小相关。<br>　　礼帽运算用来分离比邻近点亮一些的斑块。当一幅图像具有大幅的背景的时候，而微小物品比较有规律的情况下，可以使用顶帽运算进行背景提取。</li>
<li><strong>黑帽运算</strong><br>为”闭运算“的结果图与原图像之差。数学表达式为：<br><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617374855658-b2d047d0-6088-4243-a786-795b65057c72.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_21%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#height=50&amp;id=wWv6n&amp;margin=%5Bobject%20Object%5D&amp;name=image.png&amp;originHeight=50&amp;originWidth=747&amp;originalType=binary∶=1&amp;size=20646&amp;status=done&amp;style=none&amp;width=747" srcset="/img/loading.gif" lazyload alt="image.png"><br>黑帽运算后的效果图突出了比原图轮廓周围的区域更暗的区域，且这一操作和选择的核的大小相关。<br>黑帽运算用来分离比邻近点暗一些的斑块。</li>
<li><strong>API</strong></li>
</ol>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python">cv<span class="token punctuation">.</span>morphologyEx<span class="token punctuation">(</span>img<span class="token punctuation">,</span> op<span class="token punctuation">,</span> kernel<span class="token punctuation">)</span>
    img<span class="token punctuation">:</span> 要处理的图像
    op<span class="token punctuation">:</span> 处理方式：
    Kernel： 核结构<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span></span></code></pre></div>
<ol>
<li>参数：</li>
</ol>
<p><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617374834506-499ee6d6-d554-46f3-bf3d-1eebc4068026.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_20%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png"></p>
<ol>
<li><strong>示例</strong></li>
</ol>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token keyword">import</span> numpy <span class="token keyword">as</span> np
<span class="token keyword">import</span> cv2 <span class="token keyword">as</span> cv
<span class="token keyword">import</span> matplotlib<span class="token punctuation">.</span>pyplot <span class="token keyword">as</span> plt

<span class="token comment"># 1 读取图像</span>
img1 <span class="token operator">=</span> cv<span class="token punctuation">.</span>imread<span class="token punctuation">(</span><span class="token string">"./image/letter.png"</span><span class="token punctuation">)</span>
img2 <span class="token operator">=</span> cv<span class="token punctuation">.</span>imread<span class="token punctuation">(</span><span class="token string">"./image/letter.png"</span><span class="token punctuation">)</span>
<span class="token comment"># 2 创建核结构</span>
kernel <span class="token operator">=</span> np<span class="token punctuation">.</span>ones<span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">,</span> np<span class="token punctuation">.</span>uint8<span class="token punctuation">)</span>
<span class="token comment"># 3 图像的礼帽和黑帽运算</span>
cvOpen <span class="token operator">=</span> cv<span class="token punctuation">.</span>morphologyEx<span class="token punctuation">(</span>img1<span class="token punctuation">,</span> cv<span class="token punctuation">.</span>MORPH_TOPHAT<span class="token punctuation">,</span> kernel<span class="token punctuation">)</span>  <span class="token comment"># 礼帽运算</span>
cvClose <span class="token operator">=</span> cv<span class="token punctuation">.</span>morphologyEx<span class="token punctuation">(</span>img2<span class="token punctuation">,</span> cv<span class="token punctuation">.</span>MORPH_BLACKHAT<span class="token punctuation">,</span> kernel<span class="token punctuation">)</span>  <span class="token comment"># 黑帽运算</span>
<span class="token comment"># 4 图像显示</span>
fig<span class="token punctuation">,</span> axes <span class="token operator">=</span> plt<span class="token punctuation">.</span>subplots<span class="token punctuation">(</span>nrows<span class="token operator">=</span><span class="token number">2</span><span class="token punctuation">,</span> ncols<span class="token operator">=</span><span class="token number">2</span><span class="token punctuation">,</span> figsize<span class="token operator">=</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">,</span> <span class="token number">8</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>imshow<span class="token punctuation">(</span>img1<span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>set_title<span class="token punctuation">(</span><span class="token string">"原图"</span><span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">.</span>imshow<span class="token punctuation">(</span>cvOpen<span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">.</span>set_title<span class="token punctuation">(</span><span class="token string">"礼帽运算结果"</span><span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>imshow<span class="token punctuation">(</span>img2<span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>set_title<span class="token punctuation">(</span><span class="token string">"原图"</span><span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">.</span>imshow<span class="token punctuation">(</span>cvClose<span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">.</span>set_title<span class="token punctuation">(</span><span class="token string">"黑帽运算结果"</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>show<span class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617374789561-e36f7d13-78bf-41f2-846a-0d488cef9e57.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_23%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png"></p>
<h2 id="6-图像平滑"><a href="#6-图像平滑" class="headerlink" title="6. 图像平滑"></a>6. 图像平滑</h2><h3 id="6-1-图像噪声"><a href="#6-1-图像噪声" class="headerlink" title="6.1 图像噪声"></a>6.1 图像噪声</h3><p>由于图像采集、处理、传输等过程不可避免的会受到噪声的污染，妨碍人们对图像理解及分析处理。常见的图像噪声有高斯噪声、椒盐噪声等。</p>
<h4 id="6-1-1-椒盐噪声"><a href="#6-1-1-椒盐噪声" class="headerlink" title="6.1.1 椒盐噪声"></a>6.1.1 椒盐噪声</h4><p>椒盐噪声也称为脉冲噪声，是图像中经常见到的一种噪声，它是一种随机出现的白点或者黑点，可能是亮的区域有黑色像素或是在暗的区域有白色像素（或是两者皆有）。椒盐噪声的成因可能是影像讯号受到突如其来的强烈干扰而产生、类比数位转换器或位元传输错误等。例如失效的感应器导致像素值为最小值，饱和的感应器导致像素值为最大值。<br><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617375885885-a3d85457-7f4e-4b67-8a51-4016343be0f7.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_22%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png"></p>
<h4 id="6-1-2-高斯噪声"><a href="#6-1-2-高斯噪声" class="headerlink" title="6.1.2 高斯噪声"></a>6.1.2 高斯噪声</h4><p>高斯噪声是指噪声密度函数服从高斯分布的一类噪声。由于高斯噪声在空间和频域中数学上的易处理性，这种噪声(也称为正态噪声)模型经常被用于实践中。高斯随机变量 z 的概率密度函数由下式给出：<img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617376001833-af45b947-9eda-49ed-8e1f-34938b838c78.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_9%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#height=65&amp;id=Zacjr&amp;margin=%5Bobject%20Object%5D&amp;name=image.png&amp;originHeight=65&amp;originWidth=208&amp;originalType=binary∶=1&amp;size=3151&amp;status=done&amp;style=none&amp;width=208" srcset="/img/loading.gif" lazyload alt="image.png"><br>其中 z 表示灰度值，μ 表示 z 的平均值或期望值，σ 表示 z 的标准差。标准差的平方\sigma^{2}_σ_2 称为 z 的方差。高斯函数的曲线如图所示。<br><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617375856318-5b0be950-77ac-4cb4-b0c7-d5981ab2d778.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_16%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png"><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617375865502-4420295d-1876-4855-998c-98596085cef8.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_23%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png"></p>
<h3 id="6-2-图像平滑简介"><a href="#6-2-图像平滑简介" class="headerlink" title="6.2 图像平滑简介"></a>6.2 图像平滑简介</h3><p>图像平滑从信号处理的角度看就是去除其中的高频信息，保留低频信息。因此我们可以对图像实施低通滤波。低通滤波可以去除图像中的噪声，对图像进行平滑。<br>根据滤波器的不同可分为均值滤波，高斯滤波，中值滤波， 双边滤波。</p>
<h4 id="6-2-1-均值滤波"><a href="#6-2-1-均值滤波" class="headerlink" title="6.2.1 均值滤波"></a>6.2.1 均值滤波</h4><p>采用均值滤波模板对图像噪声进行滤除。令<img src="https://cdn.nlark.com/yuque/0/2021/svg/448115/1617375239079-004d5d20-619a-4893-bb42-8e3f513abca0.svg#height=26&amp;id=GcbqM&amp;originHeight=26&amp;originWidth=31&amp;originalType=binary∶=1&amp;size=0&amp;status=done&amp;style=none&amp;width=31" srcset="/img/loading.gif" lazyload alt=""> 表示中心在(x, y)点，尺寸为 m×n 的矩形子图像窗口的坐标组。 均值滤波器可表示为：<br><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617375835493-94ba0dd4-a6e1-43cf-83dc-09f0b10cd6bb.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_12%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png">由一个归一化卷积框完成的。它只是用卷积框覆盖区域所有像素的平均值来代替中心元素。<br>例如，3x3 标准化的平均过滤器如下所示：<br><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617375820770-d5964ba2-00d1-48b8-863e-fab2c4854d05.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_9%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png">均值滤波的优点是算法简单，计算速度较快，缺点是在去噪的同时去除了很多细节部分，将图像变得模糊。<br>API:</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python">cv<span class="token punctuation">.</span>blur<span class="token punctuation">(</span>src<span class="token punctuation">,</span> ksize<span class="token punctuation">,</span> anchor<span class="token punctuation">,</span> borderType<span class="token punctuation">)</span>
  src：输入图像
  ksize：卷积核的大小
  anchor：默认值 <span class="token punctuation">(</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span> ，表示核中心
  borderType：边界类型<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p>示例：</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token keyword">import</span> cv2 <span class="token keyword">as</span> cv
<span class="token keyword">import</span> numpy <span class="token keyword">as</span> np
<span class="token keyword">from</span> matplotlib <span class="token keyword">import</span> pyplot <span class="token keyword">as</span> plt

<span class="token comment"># 1 图像读取</span>
img <span class="token operator">=</span> cv<span class="token punctuation">.</span>imread<span class="token punctuation">(</span><span class="token string">'./image/dogsp.jpeg'</span><span class="token punctuation">)</span>
<span class="token comment"># 2 均值滤波</span>
blur <span class="token operator">=</span> cv<span class="token punctuation">.</span>blur<span class="token punctuation">(</span>img<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token comment"># 3 图像显示</span>
plt<span class="token punctuation">.</span>figure<span class="token punctuation">(</span>figsize<span class="token operator">=</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">,</span> <span class="token number">8</span><span class="token punctuation">)</span><span class="token punctuation">,</span> dpi<span class="token operator">=</span><span class="token number">100</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>subplot<span class="token punctuation">(</span><span class="token number">121</span><span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>imshow<span class="token punctuation">(</span>img<span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token punctuation">,</span> <span class="token punctuation">:</span><span class="token punctuation">,</span> <span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>title<span class="token punctuation">(</span><span class="token string">'原图'</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>xticks<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>yticks<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>subplot<span class="token punctuation">(</span><span class="token number">122</span><span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>imshow<span class="token punctuation">(</span>blur<span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token punctuation">,</span> <span class="token punctuation">:</span><span class="token punctuation">,</span> <span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>title<span class="token punctuation">(</span><span class="token string">'均值滤波后结果'</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>xticks<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>yticks<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>show<span class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617375798284-c005a796-bb2c-4b64-90fa-4cccfc2ee003.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_22%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png"></p>
<h4 id="6-2-2-高斯滤波"><a href="#6-2-2-高斯滤波" class="headerlink" title="6.2.2 高斯滤波"></a>6.2.2 高斯滤波</h4><p>二维高斯是构建高斯滤波器的基础，其概率分布函数如下所示：<br><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617375765245-e97fa825-af21-4637-86b7-b7833ff0e995.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_15%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png">G(x,y)的分布是一个突起的帽子的形状。这里的 σ 可以看作两个值，一个是 x 方向的标准差\sigma<em>x</em>σx<em>，另一个是 y 方向的标准差\sigma_y</em>σy_。<br><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617375759114-424b7cbc-8a3c-42d5-9232-b52dd5f3ee3f.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_23%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png"><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617375781101-2fbabbde-1b74-49d2-856d-758c1ecaccc0.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_16%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png">正态分布是一种钟形曲线，越接近中心，取值越大，越远离中心，取值越小。计算平滑结果时，只需要将”中心点”作为原点，其他点按照其在正态曲线上的位置，分配权重，就可以得到一个加权平均值。<br>高斯平滑在从图像中去除高斯噪声方面非常有效。<br><strong>高斯平滑的流程：</strong></p>
<ul>
<li>首先确定权重矩阵</li>
</ul>
<p>假定中心点的坐标是（0,0），那么距离它最近的 8 个点的坐标如下：<br><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617375744756-b50fc8d4-5513-417b-b2a3-2a18a805d8b2.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_18%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png">更远的点以此类推。<br>为了计算权重矩阵，需要设定 σ 的值。假定 σ=1.5，则模糊半径为 1 的权重矩阵如下：<br><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617375738852-f263a075-8271-49e8-8e06-1bd47c47ad89.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_20%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png">这 9 个点的权重总和等于 0.4787147，如果只计算这 9 个点的加权平均，还必须让它们的权重之和等于 1，因此上面 9 个值还要分别除以 0.4787147，得到最终的权重矩阵。<br><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617375732376-43bc0848-899c-422b-a097-7a9bfafa7192.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_19%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png"></p>
<ul>
<li>计算高斯模糊</li>
</ul>
<p>有了权重矩阵，就可以计算高斯模糊的值了。<br>假设现有 9 个像素点，灰度值（0-255）如下：<br><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617375726494-39383d76-8885-464e-8561-53b8f55ec4ef.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_18%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png">每个点乘以对应的权重值：<br><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617375718904-05fd2bea-e5e1-4b24-8bcb-3a8f7d7fd134.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_22%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png">得到<br><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617375713230-8843b8e8-9c1b-4018-998a-8c3e2a77a3cf.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_18%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png">将这 9 个值加起来，就是中心点的高斯模糊的值。<br>对所有点重复这个过程，就得到了高斯模糊后的图像。如果原图是彩色图片，可以对 RGB 三个通道分别做高斯平滑。<br>API：</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python">cv2<span class="token punctuation">.</span>GaussianBlur<span class="token punctuation">(</span>src<span class="token punctuation">,</span>ksize<span class="token punctuation">,</span>sigmaX<span class="token punctuation">,</span>sigmay<span class="token punctuation">,</span>borderType<span class="token punctuation">)</span>
  src<span class="token punctuation">:</span> 输入图像
  ksize<span class="token punctuation">:</span>高斯卷积核的大小，注意 ： 卷积核的宽度和高度都应为奇数，且可以不同
  sigmaX<span class="token punctuation">:</span> 水平方向的标准差
  sigmaY<span class="token punctuation">:</span> 垂直方向的标准差，默认值为<span class="token number">0</span>，表示与sigmaX相同
  borderType<span class="token punctuation">:</span>填充边界类型<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p><strong>示例</strong>：</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token keyword">import</span> cv2 <span class="token keyword">as</span> cv
<span class="token keyword">import</span> numpy <span class="token keyword">as</span> np
<span class="token keyword">from</span> matplotlib <span class="token keyword">import</span> pyplot <span class="token keyword">as</span> plt

<span class="token comment"># 1 图像读取</span>
img <span class="token operator">=</span> cv<span class="token punctuation">.</span>imread<span class="token punctuation">(</span><span class="token string">'./image/dogGasuss.jpeg'</span><span class="token punctuation">)</span>
<span class="token comment"># 2 高斯滤波</span>
blur <span class="token operator">=</span> cv<span class="token punctuation">.</span>GaussianBlur<span class="token punctuation">(</span>img<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span>
<span class="token comment"># 3 图像显示</span>
plt<span class="token punctuation">.</span>figure<span class="token punctuation">(</span>figsize<span class="token operator">=</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">,</span> <span class="token number">8</span><span class="token punctuation">)</span><span class="token punctuation">,</span> dpi<span class="token operator">=</span><span class="token number">100</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>subplot<span class="token punctuation">(</span><span class="token number">121</span><span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>imshow<span class="token punctuation">(</span>img<span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token punctuation">,</span> <span class="token punctuation">:</span><span class="token punctuation">,</span> <span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>title<span class="token punctuation">(</span><span class="token string">'原图'</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>xticks<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>yticks<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>subplot<span class="token punctuation">(</span><span class="token number">122</span><span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>imshow<span class="token punctuation">(</span>blur<span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token punctuation">,</span> <span class="token punctuation">:</span><span class="token punctuation">,</span> <span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>title<span class="token punctuation">(</span><span class="token string">'高斯滤波后结果'</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>xticks<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>yticks<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>show<span class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617375680991-576a8ace-4523-47d0-99df-3313eb0f70a8.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_22%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png"></p>
<h4 id="6-2-3-中值滤波"><a href="#6-2-3-中值滤波" class="headerlink" title="6.2.3 中值滤波"></a>6.2.3 中值滤波</h4><p>中值滤波是一种典型的非线性滤波技术，基本思想是用像素点邻域灰度值的中值来代替该像素点的灰度值。<br>中值滤波对椒盐噪声（salt-and-pepper noise）来说尤其有用，因为它不依赖于邻域内那些与典型值差别很大的值。<br>API：</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python">cv<span class="token punctuation">.</span>medianBlur<span class="token punctuation">(</span>src<span class="token punctuation">,</span> ksize<span class="token punctuation">)</span>
    src：输入图像
    ksize：卷积核的大小<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code></pre></div>
<p>示例：</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token keyword">import</span> cv2 <span class="token keyword">as</span> cv
<span class="token keyword">import</span> numpy <span class="token keyword">as</span> np
<span class="token keyword">from</span> matplotlib <span class="token keyword">import</span> pyplot <span class="token keyword">as</span> plt

<span class="token comment"># 1 图像读取</span>
img <span class="token operator">=</span> cv<span class="token punctuation">.</span>imread<span class="token punctuation">(</span><span class="token string">'./image/dogsp.jpeg'</span><span class="token punctuation">)</span>
<span class="token comment"># 2 中值滤波</span>
blur <span class="token operator">=</span> cv<span class="token punctuation">.</span>medianBlur<span class="token punctuation">(</span>img<span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">)</span>
<span class="token comment"># 3 图像展示</span>
plt<span class="token punctuation">.</span>figure<span class="token punctuation">(</span>figsize<span class="token operator">=</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">,</span> <span class="token number">8</span><span class="token punctuation">)</span><span class="token punctuation">,</span> dpi<span class="token operator">=</span><span class="token number">100</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>subplot<span class="token punctuation">(</span><span class="token number">121</span><span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>imshow<span class="token punctuation">(</span>img<span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token punctuation">,</span> <span class="token punctuation">:</span><span class="token punctuation">,</span> <span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>title<span class="token punctuation">(</span><span class="token string">'原图'</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>xticks<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>yticks<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>subplot<span class="token punctuation">(</span><span class="token number">122</span><span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>imshow<span class="token punctuation">(</span>blur<span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token punctuation">,</span> <span class="token punctuation">:</span><span class="token punctuation">,</span> <span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>title<span class="token punctuation">(</span><span class="token string">'中值滤波后结果'</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>xticks<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>yticks<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>show<span class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617375247382-9f988e06-7bfe-4f82-9d0a-44949f150a31.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_23%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png"></p>
<h2 id="7-直方图"><a href="#7-直方图" class="headerlink" title="7. 直方图"></a>7. 直方图</h2><h3 id="7-1-灰度直方图"><a href="#7-1-灰度直方图" class="headerlink" title="7.1 灰度直方图"></a>7.1 灰度直方图</h3><h4 id="7-1-1-原理"><a href="#7-1-1-原理" class="headerlink" title="7.1.1 原理"></a>7.1.1 原理</h4><p>直方图是对数据进行统计的一种方法，并且将统计值组织到一系列实现定义好的 bin 当中。其中， bin 为直方图中经常用到的一个概念，可以译为 “直条” 或 “组距”，其数值是从数据中计算出的特征统计量，这些数据可以是诸如梯度、方向、色彩或任何其他特征。<br>   图像直方图（Image Histogram）是用以表示数字图像中亮度分布的直方图，标绘了图像中每个亮度值的像素个数。这种直方图中，横坐标的左侧为较暗的区域，而右侧为较亮的区域。因此一张较暗图片的直方图中的数据多集中于左侧和中间部分，而整体明亮、只有少量阴影的图像则相反。<br><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617376678723-d8fe5595-5f70-484e-8b18-c8d9a5d6e116.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_23%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png">注意：直方图是根据灰度图进行绘制的，而不是彩色图像。    假设有一张图像的信息（灰度值 0 - 255，已知数字的范围包含 256 个值，于是可以按一定规律将这个范围分割成子区域（也就是 bins）。如：<br><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617376693608-91a9c642-5b14-49e3-9b6e-2fd1047fdacb.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_11%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png">然后再统计每一个 bin(i) 的像素数目。可以得到下图（其中 x 轴表示 bin，y 轴表示各个 bin 中的像素个数）：<br><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617376668953-01dcb858-4e87-4397-882a-28633f90e357.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_22%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png">直方图的一些<strong>术语和细节</strong>：</p>
<ul>
<li>dims：需要统计的特征数目。在上例中，dims = 1 ，因为仅仅统计了灰度值。</li>
<li>bins：每个特征空间子区段的数目，可译为 “直条” 或 “组距”，在上例中， bins = 16。</li>
<li>range：要统计特征的取值范围。在上例中，range = [0, 255]。</li>
</ul>
<p>直方图的<strong>意义</strong>：</p>
<ul>
<li>直方图是图像中像素强度分布的图形表达方式。</li>
<li>它统计了每一个强度值所具有的像素个数。</li>
<li>不同的图像的直方图可能是相同的</li>
</ul>
<h4 id="7-1-2-直方图的计算和绘制"><a href="#7-1-2-直方图的计算和绘制" class="headerlink" title="7.1.2 直方图的计算和绘制"></a>7.1.2 直方图的计算和绘制</h4><p>我们使用 OpenCV 中的方法统计直方图，并使用 matplotlib 将其绘制出来。<br>API：</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python">cv<span class="token punctuation">.</span>calcHist<span class="token punctuation">(</span>images<span class="token punctuation">,</span>channels<span class="token punctuation">,</span>mask<span class="token punctuation">,</span>histSize<span class="token punctuation">,</span>ranges<span class="token punctuation">[</span><span class="token punctuation">,</span>hist<span class="token punctuation">[</span><span class="token punctuation">,</span>accumulate<span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
  images<span class="token punctuation">:</span> 原图像。当传入函数时应该用中括号 <span class="token punctuation">[</span><span class="token punctuation">]</span> 括起来，例如：<span class="token punctuation">[</span>img<span class="token punctuation">]</span>。
  channels<span class="token punctuation">:</span> 如果输入图像是灰度图，它的值就是 <span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span>；如果是彩色图像的话，传入的参数可以是 <span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span>，<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span>，<span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">]</span> 它们分别对应着通道 B，G，R。 　　
  mask<span class="token punctuation">:</span> 掩模图像。要统计整幅图像的直方图就把它设为 <span class="token boolean">None</span>。但是如果你想统计图像某一部分的直方图的话，你就需要制作一个掩模图像，并使用它。（后边有例子） 　　
  histSize<span class="token punctuation">:</span>BIN 的数目。也应该用中括号括起来，例如：<span class="token punctuation">[</span><span class="token number">256</span><span class="token punctuation">]</span>。 　　
  ranges<span class="token punctuation">:</span> 像素值范围，通常为 <span class="token punctuation">[</span><span class="token number">0</span>，<span class="token number">256</span><span class="token punctuation">]</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p>示例：<br>如下图，绘制相应的直方图</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token keyword">import</span> numpy <span class="token keyword">as</span> np
<span class="token keyword">import</span> cv2 <span class="token keyword">as</span> cv
<span class="token keyword">from</span> matplotlib <span class="token keyword">import</span> pyplot <span class="token keyword">as</span> plt

<span class="token comment"># 1 直接以灰度图的方式读入</span>
img <span class="token operator">=</span> cv<span class="token punctuation">.</span>imread<span class="token punctuation">(</span><span class="token string">'./image/cat.jpeg'</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span>
<span class="token comment"># 2 统计灰度图</span>
histr <span class="token operator">=</span> cv<span class="token punctuation">.</span>calcHist<span class="token punctuation">(</span><span class="token punctuation">[</span>img<span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token boolean">None</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token number">256</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">256</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
<span class="token comment"># 3 绘制灰度图</span>
plt<span class="token punctuation">.</span>figure<span class="token punctuation">(</span>figsize<span class="token operator">=</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">,</span> <span class="token number">6</span><span class="token punctuation">)</span><span class="token punctuation">,</span> dpi<span class="token operator">=</span><span class="token number">100</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>plot<span class="token punctuation">(</span>histr<span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>grid<span class="token punctuation">(</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>show<span class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617376635328-6a2c57fb-e225-4813-9f30-fffd7caed102.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_22%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png"></p>
<h4 id="7-1-3-掩膜的应用"><a href="#7-1-3-掩膜的应用" class="headerlink" title="7.1.3 掩膜的应用"></a>7.1.3 掩膜的应用</h4><p>掩膜是用选定的图像、图形或物体，对要处理的图像进行遮挡，来控制图像 处理的区域。<br>在数字图像处理中，我们通常使用二维矩阵数组进行掩膜。掩膜是由 0 和 1 组成一个二进制图像，利用该掩膜图像要处理的图像进行掩膜，其中 1 值的区域被处理，0 值区域被屏蔽，不会处理。<br>掩膜的主要用途是：</p>
<ul>
<li>提取感兴趣区域：用预先制作的感兴趣区掩模与待处理图像进行”与“操作，得到感兴趣区图像，感兴趣区内图像值保持不变，而区外图像值都为 0。</li>
<li>屏蔽作用：用掩模对图像上某些区域作屏蔽，使其不参加处理或不参加处理参数的计算，或仅对屏蔽区作处理或统计。</li>
<li>结构特征提取：用相似性变量或图像匹配方法检测和提取图像中与掩模相似的结构特征。</li>
<li>特殊形状图像制作</li>
</ul>
<p>掩膜在遥感影像处理中使用较多，当提取道路或者河流，或者房屋时，通过一个掩膜矩阵来对图像进行像素过滤，然后将我们需要的地物或者标志突出显示出来。<br>我们使用 cv.calcHist（）来查找完整图像的直方图。 如果要查找图像某些区域的直方图，该怎么办？ 只需在要查找直方图的区域上创建一个白色的掩膜图像，否则创建黑色， 然后将其作为掩码 mask 传递即可。<br>示例：</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token keyword">import</span> numpy <span class="token keyword">as</span> np
<span class="token keyword">import</span> cv2 <span class="token keyword">as</span> cv
<span class="token keyword">from</span> matplotlib <span class="token keyword">import</span> pyplot <span class="token keyword">as</span> plt

<span class="token comment"># 1. 直接以灰度图的方式读入</span>
img <span class="token operator">=</span> cv<span class="token punctuation">.</span>imread<span class="token punctuation">(</span><span class="token string">'./image/cat.jpeg'</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span>
<span class="token comment"># 2. 创建蒙版</span>
mask <span class="token operator">=</span> np<span class="token punctuation">.</span>zeros<span class="token punctuation">(</span>img<span class="token punctuation">.</span>shape<span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token number">2</span><span class="token punctuation">]</span><span class="token punctuation">,</span> np<span class="token punctuation">.</span>uint8<span class="token punctuation">)</span>
mask<span class="token punctuation">[</span><span class="token number">400</span><span class="token punctuation">:</span><span class="token number">650</span><span class="token punctuation">,</span> <span class="token number">200</span><span class="token punctuation">:</span><span class="token number">500</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">255</span>
<span class="token comment"># 3.掩模</span>
masked_img <span class="token operator">=</span> cv<span class="token punctuation">.</span>bitwise_and<span class="token punctuation">(</span>img<span class="token punctuation">,</span> img<span class="token punctuation">,</span> mask<span class="token operator">=</span>mask<span class="token punctuation">)</span>
<span class="token comment"># 4. 统计掩膜后图像的灰度图</span>
mask_histr <span class="token operator">=</span> cv<span class="token punctuation">.</span>calcHist<span class="token punctuation">(</span><span class="token punctuation">[</span>img<span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">,</span> mask<span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token number">256</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">256</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
<span class="token comment"># 5. 图像展示</span>
fig<span class="token punctuation">,</span> axes <span class="token operator">=</span> plt<span class="token punctuation">.</span>subplots<span class="token punctuation">(</span>nrows<span class="token operator">=</span><span class="token number">2</span><span class="token punctuation">,</span> ncols<span class="token operator">=</span><span class="token number">2</span><span class="token punctuation">,</span> figsize<span class="token operator">=</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">,</span> <span class="token number">8</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>imshow<span class="token punctuation">(</span>img<span class="token punctuation">,</span> cmap<span class="token operator">=</span>plt<span class="token punctuation">.</span>cm<span class="token punctuation">.</span>gray<span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>set_title<span class="token punctuation">(</span><span class="token string">"原图"</span><span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">.</span>imshow<span class="token punctuation">(</span>mask<span class="token punctuation">,</span> cmap<span class="token operator">=</span>plt<span class="token punctuation">.</span>cm<span class="token punctuation">.</span>gray<span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">.</span>set_title<span class="token punctuation">(</span><span class="token string">"蒙版数据"</span><span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>imshow<span class="token punctuation">(</span>masked_img<span class="token punctuation">,</span> cmap<span class="token operator">=</span>plt<span class="token punctuation">.</span>cm<span class="token punctuation">.</span>gray<span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>set_title<span class="token punctuation">(</span><span class="token string">"掩膜后数据"</span><span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">.</span>plot<span class="token punctuation">(</span>mask_histr<span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">.</span>grid<span class="token punctuation">(</span><span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">.</span>set_title<span class="token punctuation">(</span><span class="token string">"灰度直方图"</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>show<span class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617376623443-6efa5f2c-24a5-4f69-9670-262f67cf5bb0.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_22%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png"></p>
<h3 id="7-2-直方图均衡化"><a href="#7-2-直方图均衡化" class="headerlink" title="7.2 直方图均衡化"></a>7.2 直方图均衡化</h3><h4 id="7-2-1-原理与应用"><a href="#7-2-1-原理与应用" class="headerlink" title="7.2.1 原理与应用"></a>7.2.1 原理与应用</h4><h6 id="想象一下，如果一副图像中的大多数像素点的像素值都集中在某一个小的灰度值值范围之内会怎样呢？如果一幅图像整体很亮，那所有的像素值的取值个数应该都会很高。所以应该把它的直方图做一个横向拉伸（如下图），就可以扩大图像像素值的分布范围，提高图像的对比度，这就是直方图均衡化要做的事情。"><a href="#想象一下，如果一副图像中的大多数像素点的像素值都集中在某一个小的灰度值值范围之内会怎样呢？如果一幅图像整体很亮，那所有的像素值的取值个数应该都会很高。所以应该把它的直方图做一个横向拉伸（如下图），就可以扩大图像像素值的分布范围，提高图像的对比度，这就是直方图均衡化要做的事情。" class="headerlink" title="想象一下，如果一副图像中的大多数像素点的像素值都集中在某一个小的灰度值值范围之内会怎样呢？如果一幅图像整体很亮，那所有的像素值的取值个数应该都会很高。所以应该把它的直方图做一个横向拉伸（如下图），就可以扩大图像像素值的分布范围，提高图像的对比度，这就是直方图均衡化要做的事情。"></a>想象一下，如果一副图像中的大多数像素点的像素值都集中在某一个小的灰度值值范围之内会怎样呢？如果一幅图像整体很亮，那所有的像素值的取值个数应该都会很高。所以应该把它的直方图做一个横向拉伸（如下图），就可以扩大图像像素值的分布范围，提高图像的对比度，这就是直方图均衡化要做的事情。</h6><p><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617376615886-e5725fde-fc20-47e8-b547-ea602bbadade.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_12%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png"></p>
<h6 id="“直方图均衡化”是把原始图像的灰度直方图从比较集中的某个灰度区间变成在更广泛灰度范围内的分布。直方图均衡化就是对图像进行非线性拉伸，重新分配图像像素值，使一定灰度范围内的像素数量大致相同。"><a href="#“直方图均衡化”是把原始图像的灰度直方图从比较集中的某个灰度区间变成在更广泛灰度范围内的分布。直方图均衡化就是对图像进行非线性拉伸，重新分配图像像素值，使一定灰度范围内的像素数量大致相同。" class="headerlink" title="“直方图均衡化”是把原始图像的灰度直方图从比较集中的某个灰度区间变成在更广泛灰度范围内的分布。直方图均衡化就是对图像进行非线性拉伸，重新分配图像像素值，使一定灰度范围内的像素数量大致相同。"></a>“直方图均衡化”是把原始图像的灰度直方图从比较集中的某个灰度区间变成在更广泛灰度范围内的分布。直方图均衡化就是对图像进行非线性拉伸，重新分配图像像素值，使一定灰度范围内的像素数量大致相同。</h6><h6 id="这种方法提高图像整体的对比度，特别是有用数据的像素值分布比较接近时，在-X-光图像中使用广泛，可以提高骨架结构的显示，另外在曝光过度或不足的图像中可以更好的突出细节。"><a href="#这种方法提高图像整体的对比度，特别是有用数据的像素值分布比较接近时，在-X-光图像中使用广泛，可以提高骨架结构的显示，另外在曝光过度或不足的图像中可以更好的突出细节。" class="headerlink" title="这种方法提高图像整体的对比度，特别是有用数据的像素值分布比较接近时，在 X 光图像中使用广泛，可以提高骨架结构的显示，另外在曝光过度或不足的图像中可以更好的突出细节。"></a>这种方法提高图像整体的对比度，特别是有用数据的像素值分布比较接近时，在 X 光图像中使用广泛，可以提高骨架结构的显示，另外在曝光过度或不足的图像中可以更好的突出细节。</h6><p>使用 opencv 进行直方图统计时，使用的是：<br>API：</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python">cv<span class="token punctuation">.</span>equalizeHist<span class="token punctuation">(</span>img<span class="token punctuation">)</span>
	img<span class="token punctuation">:</span> 灰度图像<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre></div>
<p>返回：</p>
<ul>
<li>dst : 均衡化后的结果</li>
</ul>
<p>示例：</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token keyword">import</span> numpy <span class="token keyword">as</span> np
<span class="token keyword">import</span> cv2 <span class="token keyword">as</span> cv
<span class="token keyword">from</span> matplotlib <span class="token keyword">import</span> pyplot <span class="token keyword">as</span> plt

<span class="token comment"># 1. 直接以灰度图的方式读入</span>
img <span class="token operator">=</span> cv<span class="token punctuation">.</span>imread<span class="token punctuation">(</span><span class="token string">'./image/cat.jpeg'</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span>
<span class="token comment"># 2. 均衡化处理</span>
dst <span class="token operator">=</span> cv<span class="token punctuation">.</span>equalizeHist<span class="token punctuation">(</span>img<span class="token punctuation">)</span>
<span class="token comment"># 3. 结果展示</span>
fig<span class="token punctuation">,</span> axes <span class="token operator">=</span> plt<span class="token punctuation">.</span>subplots<span class="token punctuation">(</span>nrows<span class="token operator">=</span><span class="token number">2</span><span class="token punctuation">,</span> ncols<span class="token operator">=</span><span class="token number">2</span><span class="token punctuation">,</span> figsize<span class="token operator">=</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">,</span> <span class="token number">8</span><span class="token punctuation">)</span><span class="token punctuation">,</span> dpi<span class="token operator">=</span><span class="token number">100</span><span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>imshow<span class="token punctuation">(</span>img<span class="token punctuation">,</span> cmap<span class="token operator">=</span>plt<span class="token punctuation">.</span>cm<span class="token punctuation">.</span>gray<span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>set_title<span class="token punctuation">(</span><span class="token string">"原图"</span><span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">.</span>imshow<span class="token punctuation">(</span>dst<span class="token punctuation">,</span> cmap<span class="token operator">=</span>plt<span class="token punctuation">.</span>cm<span class="token punctuation">.</span>gray<span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">.</span>set_title<span class="token punctuation">(</span><span class="token string">"均衡化后结果"</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>show<span class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617376577195-52b44c01-6629-4c05-962e-02d45e50232f.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_22%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png"></p>
<h4 id="7-2-2-自适应的直方图均衡化"><a href="#7-2-2-自适应的直方图均衡化" class="headerlink" title="7.2.2 自适应的直方图均衡化"></a>7.2.2 自适应的直方图均衡化</h4><h6 id="上述的直方图均衡，我们考虑的是图像的全局对比度。-的确在进行完直方图均衡化之后，图片背景的对比度被改变了，在猫腿这里太暗，我们丢失了很多信息，所以在许多情况下，这样做的效果并不好。如下图所示，对比下两幅图像中雕像的画面，由于太亮我们丢失了很多信息。"><a href="#上述的直方图均衡，我们考虑的是图像的全局对比度。-的确在进行完直方图均衡化之后，图片背景的对比度被改变了，在猫腿这里太暗，我们丢失了很多信息，所以在许多情况下，这样做的效果并不好。如下图所示，对比下两幅图像中雕像的画面，由于太亮我们丢失了很多信息。" class="headerlink" title="上述的直方图均衡，我们考虑的是图像的全局对比度。 的确在进行完直方图均衡化之后，图片背景的对比度被改变了，在猫腿这里太暗，我们丢失了很多信息，所以在许多情况下，这样做的效果并不好。如下图所示，对比下两幅图像中雕像的画面，由于太亮我们丢失了很多信息。"></a>上述的直方图均衡，我们考虑的是图像的全局对比度。 的确在进行完直方图均衡化之后，图片背景的对比度被改变了，在猫腿这里太暗，我们丢失了很多信息，所以在许多情况下，这样做的效果并不好。如下图所示，对比下两幅图像中雕像的画面，由于太亮我们丢失了很多信息。</h6><p><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617376570455-7142ab38-c36c-4b4b-aeaa-d21ef094c538.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_23%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png">为了解决这个问题， 需要使用自适应的直方图均衡化。 此时， 整幅图像会被分成很多小块，这些小块被称为“tiles”（在 OpenCV 中 tiles 的 大小默认是 8x8），然后再对每一个小块分别进行直方图均衡化。 所以在每一个的区域中， 直方图会集中在某一个小的区域中）。如果有噪声的话，噪声会被放大。为了避免这种情况的出现要使用对比度限制。对于每个小块来说，如果直方图中的 bin 超过对比度的上限的话，就把 其中的像素点均匀分散到其他 bins 中，然后在进行直方图均衡化。<br><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617376564263-1403744a-7809-4bd2-8d72-a2192772f7e0.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_22%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png">最后，为了 去除每一个小块之间的边界，再使用双线性差值，对每一小块进行拼接。<br>API：</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python">cv<span class="token punctuation">.</span>createCLAHE<span class="token punctuation">(</span>clipLimit<span class="token punctuation">,</span> tileGridSize<span class="token punctuation">)</span>
  clipLimit<span class="token punctuation">:</span> 对比度限制，默认是<span class="token number">40</span>
  tileGridSize<span class="token punctuation">:</span> 分块的大小，默认为<span class="token number">8</span><span class="token operator">*</span><span class="token number">88</span>∗<span class="token number">8</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code></pre></div>
<p>示例：</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token keyword">import</span> numpy <span class="token keyword">as</span> np
<span class="token keyword">import</span> cv2 <span class="token keyword">as</span> cv
<span class="token keyword">from</span> matplotlib <span class="token keyword">import</span> pyplot <span class="token keyword">as</span> plt

<span class="token comment"># 1. 以灰度图形式读取图像</span>
img <span class="token operator">=</span> cv<span class="token punctuation">.</span>imread<span class="token punctuation">(</span><span class="token string">'./image/cat.jpeg'</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span>
<span class="token comment"># 2. 创建一个自适应均衡化的对象，并应用于图像</span>
clahe <span class="token operator">=</span> cv<span class="token punctuation">.</span>createCLAHE<span class="token punctuation">(</span>clipLimit<span class="token operator">=</span><span class="token number">2.0</span><span class="token punctuation">,</span> tileGridSize<span class="token operator">=</span><span class="token punctuation">(</span><span class="token number">8</span><span class="token punctuation">,</span> <span class="token number">8</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
cl1 <span class="token operator">=</span> clahe<span class="token punctuation">.</span><span class="token builtin">apply</span><span class="token punctuation">(</span>img<span class="token punctuation">)</span>
<span class="token comment"># 3. 图像展示</span>
fig<span class="token punctuation">,</span> axes <span class="token operator">=</span> plt<span class="token punctuation">.</span>subplots<span class="token punctuation">(</span>nrows<span class="token operator">=</span><span class="token number">1</span><span class="token punctuation">,</span> ncols<span class="token operator">=</span><span class="token number">2</span><span class="token punctuation">,</span> figsize<span class="token operator">=</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">,</span> <span class="token number">8</span><span class="token punctuation">)</span><span class="token punctuation">,</span> dpi<span class="token operator">=</span><span class="token number">100</span><span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>imshow<span class="token punctuation">(</span>img<span class="token punctuation">,</span> cmap<span class="token operator">=</span>plt<span class="token punctuation">.</span>cm<span class="token punctuation">.</span>gray<span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>set_title<span class="token punctuation">(</span><span class="token string">"原图"</span><span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">.</span>imshow<span class="token punctuation">(</span>cl1<span class="token punctuation">,</span> cmap<span class="token operator">=</span>plt<span class="token punctuation">.</span>cm<span class="token punctuation">.</span>gray<span class="token punctuation">)</span>
axes<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">.</span>set_title<span class="token punctuation">(</span><span class="token string">"自适应均衡化后的结果"</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>show<span class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617376557497-b765bbed-92ea-4484-99ef-b1a7d8434eb0.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_22%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png"></p>
<h2 id="8-边缘检测"><a href="#8-边缘检测" class="headerlink" title="8. 边缘检测"></a>8. 边缘检测</h2><h3 id="8-1-原理"><a href="#8-1-原理" class="headerlink" title="8.1 原理"></a>8.1 原理</h3><p>边缘检测是图像处理和计算机视觉中的基本问题，边缘检测的目的是标识数字图像中亮度变化明显的点。图像属性中的显著变化通常反映了属性的重要事件和变化。边缘的表现形式如下图所示：<br><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617377190404-c2a71ea9-27b3-4799-aba5-823d631a7e59.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_23%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png"></p>
<h6 id="图像边缘检测大幅度地减少了数据量，并且剔除了可以认为不相关的信息，保留了图像重要的结构属性。有许多方法用于边缘检测，它们的绝大部分可以划分为两类：基于搜索和基于零穿越。"><a href="#图像边缘检测大幅度地减少了数据量，并且剔除了可以认为不相关的信息，保留了图像重要的结构属性。有许多方法用于边缘检测，它们的绝大部分可以划分为两类：基于搜索和基于零穿越。" class="headerlink" title="图像边缘检测大幅度地减少了数据量，并且剔除了可以认为不相关的信息，保留了图像重要的结构属性。有许多方法用于边缘检测，它们的绝大部分可以划分为两类：基于搜索和基于零穿越。"></a>图像边缘检测大幅度地减少了数据量，并且剔除了可以认为不相关的信息，保留了图像重要的结构属性。有许多方法用于边缘检测，它们的绝大部分可以划分为两类：<strong>基于搜索</strong>和<strong>基于零穿越</strong>。</h6><ul>
<li>基于搜索：通过寻找图像一阶导数中的最大值来检测边界，然后利用计算结果估计边缘的局部方向，通常采用梯度的方向，并利用此方向找到局部梯度模的最大值，代表算法是 Sobel 算子和 Scharr 算子。<br><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617377178784-2f2a9212-74cc-4651-997d-ada83b56e57f.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_21%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#height=209&amp;id=TKn3a&amp;margin=%5Bobject%20Object%5D&amp;name=image.png&amp;originHeight=279&amp;originWidth=738&amp;originalType=binary∶=1&amp;size=179409&amp;status=done&amp;style=none&amp;width=554" srcset="/img/loading.gif" lazyload alt="image.png"></li>
<li>基于零穿越：通过寻找图像二阶导数零穿越来寻找边界，代表算法是 Laplacian 算子。<br><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617377171251-7516ea06-812d-4a24-8a3a-21f2e5c845ff.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_18%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#height=335&amp;id=X22A8&amp;margin=%5Bobject%20Object%5D&amp;name=image.png&amp;originHeight=447&amp;originWidth=620&amp;originalType=binary∶=1&amp;size=127141&amp;status=done&amp;style=none&amp;width=465" srcset="/img/loading.gif" lazyload alt="image.png"></li>
</ul>
<h3 id="8-2-Sobel-检测算子"><a href="#8-2-Sobel-检测算子" class="headerlink" title="8.2 Sobel 检测算子"></a>8.2 Sobel 检测算子</h3><p>Sobel 边缘检测算法比较简单，实际应用中效率比 canny 边缘检测效率要高，但是边缘不如 Canny 检测的准确，但是很多实际应用的场合，sobel 边缘却是首选，Sobel 算子是高斯平滑与微分操作的结合体，所以其抗噪声能力很强，用途较多。尤其是效率要求较高，而对细纹理不太关心的时候。</p>
<h4 id="8-2-1-方法"><a href="#8-2-1-方法" class="headerlink" title="8.2.1 方法"></a>8.2.1 方法</h4><p>对于不连续的函数，一阶导数可以写作：<br><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617377164280-c85606e8-79fb-47b9-b006-e3e9b8a4c077.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_11%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png">或<br><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617377156190-28c86fd2-22ed-4222-afa5-6994e3381cdd.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_11%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png">所以有：<br><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617377133476-ee259707-0799-4c31-acb2-18082604c5dc.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_13%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png">假设要处理的图像为 I<em>I</em>，在两个方向求导:</p>
<ul>
<li><strong>水平变化</strong>: 将图像 I<em>I</em> 与奇数大小的模版进行卷积，结果为 G<em>x_Gx</em>。比如，当模板大小为 3 时, G<em>x_Gx</em>为:</li>
</ul>
<p><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617377114292-a35d555e-6463-41f4-877e-d6acb774b34f.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_11%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png"></p>
<ul>
<li><strong>垂直变化</strong>: 将图像 I<em>I</em>与奇数大小的模板进行卷积，结果为 G<em>y_Gy</em>。比如，当模板大小为 3 时, G<em>y_Gy</em>为:</li>
</ul>
<p><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617377098548-d1bd10e9-df5c-475e-9da1-17dbbe0fd576.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_11%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png">在图像的每一点，结合以上两个结果求出：<br><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617377084686-0be8d4b5-eb61-4787-bff9-d2085b730b9a.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_9%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png">统计极大值所在的位置，就是图像的边缘。<br><strong>注意</strong>：当内核大小为 3 时, 以上 Sobel 内核可能产生比较明显的误差， 为解决这一问题，我们使用 Scharr 函数，但该函数仅作用于大小为 3 的内核。该函数的运算与 Sobel 函数一样快，但结果却更加精确，其计算方法为:<br><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617377073536-78f87609-40c3-4c42-8332-dc9159c41ac4.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_12%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png"></p>
<h4 id="8-2-2-应用"><a href="#8-2-2-应用" class="headerlink" title="8.2.2 应用"></a>8.2.2 应用</h4><p>利用 OpenCV 进行 sobel 边缘检测的 API 是：</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python">Sobel_x_or_y <span class="token operator">=</span> cv<span class="token punctuation">.</span>Sobel<span class="token punctuation">(</span>src<span class="token punctuation">,</span> ddepth<span class="token punctuation">,</span> dx<span class="token punctuation">,</span> dy<span class="token punctuation">,</span> dst<span class="token punctuation">,</span> ksize<span class="token punctuation">,</span> scale<span class="token punctuation">,</span> delta<span class="token punctuation">,</span> borderType<span class="token punctuation">)</span>
    src：传入的图像
    ddepth<span class="token punctuation">:</span> 图像的深度
    dx和dy<span class="token punctuation">:</span> 指求导的阶数，<span class="token number">0</span>表示这个方向上没有求导，取值为<span class="token number">0</span>、<span class="token number">1</span>。
    ksize<span class="token punctuation">:</span> 是Sobel算子的大小，即卷积核的大小，必须为奇数<span class="token number">1</span>、<span class="token number">3</span>、<span class="token number">5</span>、<span class="token number">7</span>，默认为<span class="token number">3</span>。
    注意：如果ksize<span class="token operator">=</span><span class="token operator">-</span><span class="token number">1</span>，就演变成为3x3的Scharr算子。
    scale：缩放导数的比例常数，默认情况为没有伸缩系数。
    borderType：图像边界的模式，默认值为cv2<span class="token punctuation">.</span>BORDER_DEFAULT。<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p>Sobel 函数求完导数后会有负值，还有会大于 255 的值。而原图像是 uint8，即 8 位无符号数，所以 Sobel 建立的图像位数不够，会有截断。因此要使用 16 位有符号的数据类型，即 cv2.CV_16S。处理完图像后，再使用 cv2.convertScaleAbs()函数将其转回原来的 uint8 格式，否则图像无法显示。<br>Sobel 算子是在两个方向计算的，最后还需要用 cv2.addWeighted( )函数将其组合起来</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python">Scale_abs <span class="token operator">=</span> cv<span class="token punctuation">.</span>convertScaleAbs<span class="token punctuation">(</span>x<span class="token punctuation">)</span>  <span class="token comment"># 格式转换函数</span>
result <span class="token operator">=</span> cv<span class="token punctuation">.</span>addWeighted<span class="token punctuation">(</span>src1<span class="token punctuation">,</span> alpha<span class="token punctuation">,</span> src2<span class="token punctuation">,</span> beta<span class="token punctuation">)</span> <span class="token comment"># 图像混合</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre></div>
<p>示例：</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token keyword">import</span> cv2 <span class="token keyword">as</span> cv
<span class="token keyword">import</span> numpy <span class="token keyword">as</span> np
<span class="token keyword">from</span> matplotlib <span class="token keyword">import</span> pyplot <span class="token keyword">as</span> plt

<span class="token comment"># 1 读取图像</span>
img <span class="token operator">=</span> cv<span class="token punctuation">.</span>imread<span class="token punctuation">(</span><span class="token string">'./image/horse.jpg'</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span>
<span class="token comment"># 2 计算Sobel卷积结果</span>
x <span class="token operator">=</span> cv<span class="token punctuation">.</span>Sobel<span class="token punctuation">(</span>img<span class="token punctuation">,</span> cv<span class="token punctuation">.</span>CV_16S<span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span>
y <span class="token operator">=</span> cv<span class="token punctuation">.</span>Sobel<span class="token punctuation">(</span>img<span class="token punctuation">,</span> cv<span class="token punctuation">.</span>CV_16S<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span>
<span class="token comment"># 3 将数据进行转换</span>
Scale_absX <span class="token operator">=</span> cv<span class="token punctuation">.</span>convertScaleAbs<span class="token punctuation">(</span>x<span class="token punctuation">)</span>  <span class="token comment"># convert 转换  scale 缩放</span>
Scale_absY <span class="token operator">=</span> cv<span class="token punctuation">.</span>convertScaleAbs<span class="token punctuation">(</span>y<span class="token punctuation">)</span>
<span class="token comment"># 4 结果合成</span>
result <span class="token operator">=</span> cv<span class="token punctuation">.</span>addWeighted<span class="token punctuation">(</span>Scale_absX<span class="token punctuation">,</span> <span class="token number">0.5</span><span class="token punctuation">,</span> Scale_absY<span class="token punctuation">,</span> <span class="token number">0.5</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span>
<span class="token comment"># 5 图像显示</span>
plt<span class="token punctuation">.</span>figure<span class="token punctuation">(</span>figsize<span class="token operator">=</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">,</span> <span class="token number">8</span><span class="token punctuation">)</span><span class="token punctuation">,</span> dpi<span class="token operator">=</span><span class="token number">100</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>subplot<span class="token punctuation">(</span><span class="token number">121</span><span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>imshow<span class="token punctuation">(</span>img<span class="token punctuation">,</span> cmap<span class="token operator">=</span>plt<span class="token punctuation">.</span>cm<span class="token punctuation">.</span>gray<span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>title<span class="token punctuation">(</span><span class="token string">'原图'</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>xticks<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>yticks<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>subplot<span class="token punctuation">(</span><span class="token number">122</span><span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>imshow<span class="token punctuation">(</span>result<span class="token punctuation">,</span> cmap<span class="token operator">=</span>plt<span class="token punctuation">.</span>cm<span class="token punctuation">.</span>gray<span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>title<span class="token punctuation">(</span><span class="token string">'Sobel滤波后结果'</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>xticks<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>yticks<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>show<span class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617377034799-83b2e7a5-ef7a-4439-8094-ef9db3e81348.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_22%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png">将上述代码中计算 sobel 算子的部分中将 ksize 设为-1，就是利用 Scharr 进行边缘检测。</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python">x <span class="token operator">=</span> cv<span class="token punctuation">.</span>Sobel<span class="token punctuation">(</span>img<span class="token punctuation">,</span> cv<span class="token punctuation">.</span>CV_16S<span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> ksize <span class="token operator">=</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span>
y <span class="token operator">=</span> cv<span class="token punctuation">.</span>Sobel<span class="token punctuation">(</span>img<span class="token punctuation">,</span> cv<span class="token punctuation">.</span>CV_16S<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> ksize <span class="token operator">=</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre></div>
<p><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617377022361-4ec9ad73-a7a5-4ab2-a779-7c668b5596bf.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_22%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png"></p>
<h3 id="8-3-Laplacian-算子"><a href="#8-3-Laplacian-算子" class="headerlink" title="8.3 Laplacian 算子"></a>8.3 Laplacian 算子</h3><p>Laplacian 是利用二阶导数来检测边缘 。 因为图像是 “<em>2 维</em>”, 我们需要在两个方向求导，如下式所示：<br><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617377016331-be2787d2-aa58-49ce-9dc0-2c99a91c9b94.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_9%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png">那不连续函数的二阶导数是：<br><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617376999678-19e56a4d-05f8-4c5b-bf8b-86803e956508.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_15%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png">那使用的卷积核是：<br><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617376988035-b58adb27-37cd-447e-a4bd-fa7ffacc8a51.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_9%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png">API：</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python">cv<span class="token punctuation">.</span>Laplacian<span class="token punctuation">(</span>src<span class="token punctuation">,</span> ddepth<span class="token punctuation">[</span><span class="token punctuation">,</span> dst<span class="token punctuation">[</span><span class="token punctuation">,</span> ksize<span class="token punctuation">[</span><span class="token punctuation">,</span> scale<span class="token punctuation">[</span><span class="token punctuation">,</span> delta<span class="token punctuation">[</span><span class="token punctuation">,</span> borderType<span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
  Src<span class="token punctuation">:</span> 需要处理的图像
  Ddepth<span class="token punctuation">:</span> 图像的深度，<span class="token operator">-</span><span class="token number">1</span>表示采用的是原图像相同的深度，目标图像的深度必须大于等于原图像的深度
  ksize：算子的大小，即卷积核的大小，必须为<span class="token number">1</span><span class="token punctuation">,</span><span class="token number">3</span><span class="token punctuation">,</span><span class="token number">5</span><span class="token punctuation">,</span><span class="token number">7</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span></span></code></pre></div>
<p>示例：</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token keyword">import</span> cv2 <span class="token keyword">as</span> cv
<span class="token keyword">import</span> numpy <span class="token keyword">as</span> np
<span class="token keyword">from</span> matplotlib <span class="token keyword">import</span> pyplot <span class="token keyword">as</span> plt

<span class="token comment"># 1 读取图像</span>
img <span class="token operator">=</span> cv<span class="token punctuation">.</span>imread<span class="token punctuation">(</span><span class="token string">'./image/horse.jpg'</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span>
<span class="token comment"># 2 laplacian转换</span>
result <span class="token operator">=</span> cv<span class="token punctuation">.</span>Laplacian<span class="token punctuation">(</span>img<span class="token punctuation">,</span> cv<span class="token punctuation">.</span>CV_16S<span class="token punctuation">)</span>
Scale_abs <span class="token operator">=</span> cv<span class="token punctuation">.</span>convertScaleAbs<span class="token punctuation">(</span>result<span class="token punctuation">)</span>
<span class="token comment"># 3 图像展示</span>
plt<span class="token punctuation">.</span>figure<span class="token punctuation">(</span>figsize<span class="token operator">=</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">,</span> <span class="token number">8</span><span class="token punctuation">)</span><span class="token punctuation">,</span> dpi<span class="token operator">=</span><span class="token number">100</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>subplot<span class="token punctuation">(</span><span class="token number">121</span><span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>imshow<span class="token punctuation">(</span>img<span class="token punctuation">,</span> cmap<span class="token operator">=</span>plt<span class="token punctuation">.</span>cm<span class="token punctuation">.</span>gray<span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>title<span class="token punctuation">(</span><span class="token string">'原图'</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>xticks<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>yticks<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>subplot<span class="token punctuation">(</span><span class="token number">122</span><span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>imshow<span class="token punctuation">(</span>Scale_abs<span class="token punctuation">,</span> cmap<span class="token operator">=</span>plt<span class="token punctuation">.</span>cm<span class="token punctuation">.</span>gray<span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>title<span class="token punctuation">(</span><span class="token string">'Laplacian检测后结果'</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>xticks<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>yticks<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>show<span class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617376952463-e93b42ef-dbe2-47aa-92c9-3bc78bcc64e9.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_22%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png"></p>
<h3 id="8-4-Canny-边缘检测"><a href="#8-4-Canny-边缘检测" class="headerlink" title="8.4 Canny 边缘检测"></a>8.4 Canny 边缘检测</h3><p>Canny 边缘检测算法是一种非常流行的边缘检测算法，是 John F. Canny 于 1986 年提出的，被认为是最优的边缘检测算法。</p>
<h4 id="8-4-1-原理"><a href="#8-4-1-原理" class="headerlink" title="8.4.1 原理"></a>8.4.1 原理</h4><p>Canny 边缘检测算法是由 4 步构成，分别介绍如下：</p>
<ul>
<li>第一步：噪声去除<br>由于边缘检测很容易受到噪声的影响，所以首先使用$5*5$高斯滤波器去除噪声，在图像平滑那一章节中已经介绍过。</li>
<li>第二步：计算图像梯度</li>
</ul>
<h6 id="对平滑后的图像使用-Sobel-算子计算水平方向和竖直方向的一阶导数（Gx-和-Gy）。根据得到的这两幅梯度图（Gx-和-Gy）找到边界的梯度和方向，公式如下"><a href="#对平滑后的图像使用-Sobel-算子计算水平方向和竖直方向的一阶导数（Gx-和-Gy）。根据得到的这两幅梯度图（Gx-和-Gy）找到边界的梯度和方向，公式如下" class="headerlink" title="对平滑后的图像使用 Sobel 算子计算水平方向和竖直方向的一阶导数（Gx 和 Gy）。根据得到的这两幅梯度图（Gx 和 Gy）找到边界的梯度和方向，公式如下:"></a>对平滑后的图像使用 Sobel 算子计算水平方向和竖直方向的一阶导数（Gx 和 Gy）。根据得到的这两幅梯度图（Gx 和 Gy）找到边界的梯度和方向，公式如下:</h6><p><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617376937104-e4869760-be44-41f0-aac1-fd6550fd872a.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_14%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png"></p>
<h6 id="如果某个像素点是边缘，则其梯度方向总是垂直与边缘垂直。梯度方向被归为四类：垂直，水平，和两个对角线方向。"><a href="#如果某个像素点是边缘，则其梯度方向总是垂直与边缘垂直。梯度方向被归为四类：垂直，水平，和两个对角线方向。" class="headerlink" title="如果某个像素点是边缘，则其梯度方向总是垂直与边缘垂直。梯度方向被归为四类：垂直，水平，和两个对角线方向。"></a>如果某个像素点是边缘，则其梯度方向总是垂直与边缘垂直。梯度方向被归为四类：垂直，水平，和两个对角线方向。</h6><ul>
<li>第三步：非极大值抑制</li>
</ul>
<h6 id="在获得梯度的方向和大小之后，对整幅图像进行扫描，去除那些非边界上的点。对每一个像素进行检查，看这个点的梯度是不是周围具有相同梯度方向的点中最大的。如下图所示："><a href="#在获得梯度的方向和大小之后，对整幅图像进行扫描，去除那些非边界上的点。对每一个像素进行检查，看这个点的梯度是不是周围具有相同梯度方向的点中最大的。如下图所示：" class="headerlink" title="在获得梯度的方向和大小之后，对整幅图像进行扫描，去除那些非边界上的点。对每一个像素进行检查，看这个点的梯度是不是周围具有相同梯度方向的点中最大的。如下图所示："></a>在获得梯度的方向和大小之后，对整幅图像进行扫描，去除那些非边界上的点。对每一个像素进行检查，看这个点的梯度是不是周围具有相同梯度方向的点中最大的。如下图所示：</h6><p><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617376919582-7251825c-727f-477b-b029-eeed0cad0cb1.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_18%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png"></p>
<h6 id="A-点位于图像的边缘，在其梯度变化方向，选择像素点-B-和-C，用来检验-A-点的梯度是否为极大值，若为极大值，则进行保留，否则-A-点被抑制，最终的结果是具有“细边”的二进制图像。"><a href="#A-点位于图像的边缘，在其梯度变化方向，选择像素点-B-和-C，用来检验-A-点的梯度是否为极大值，若为极大值，则进行保留，否则-A-点被抑制，最终的结果是具有“细边”的二进制图像。" class="headerlink" title="A 点位于图像的边缘，在其梯度变化方向，选择像素点 B 和 C，用来检验 A 点的梯度是否为极大值，若为极大值，则进行保留，否则 A 点被抑制，最终的结果是具有“细边”的二进制图像。"></a>A 点位于图像的边缘，在其梯度变化方向，选择像素点 B 和 C，用来检验 A 点的梯度是否为极大值，若为极大值，则进行保留，否则 A 点被抑制，最终的结果是具有“细边”的二进制图像。</h6><ul>
<li>第四步：滞后阈值</li>
</ul>
<h6 id="现在要确定真正的边界。-我们设置两个阈值：-minVal-和-maxVal。-当图像的灰度梯度高于-maxVal-时被认为是真的边界，-低于-minVal-的边界会被抛弃。如果介于两者之间的话，就要看这个点是否与某个被确定为真正的边界点相连，如果是就认为它也是边界点，如果不是就抛弃。如下图："><a href="#现在要确定真正的边界。-我们设置两个阈值：-minVal-和-maxVal。-当图像的灰度梯度高于-maxVal-时被认为是真的边界，-低于-minVal-的边界会被抛弃。如果介于两者之间的话，就要看这个点是否与某个被确定为真正的边界点相连，如果是就认为它也是边界点，如果不是就抛弃。如下图：" class="headerlink" title="现在要确定真正的边界。 我们设置两个阈值： minVal 和 maxVal。 当图像的灰度梯度高于 maxVal 时被认为是真的边界， 低于 minVal 的边界会被抛弃。如果介于两者之间的话，就要看这个点是否与某个被确定为真正的边界点相连，如果是就认为它也是边界点，如果不是就抛弃。如下图："></a>现在要确定真正的边界。 我们设置两个阈值： minVal 和 maxVal。 当图像的灰度梯度高于 maxVal 时被认为是真的边界， 低于 minVal 的边界会被抛弃。如果介于两者之间的话，就要看这个点是否与某个被确定为真正的边界点相连，如果是就认为它也是边界点，如果不是就抛弃。如下图：</h6><p><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617376911750-bf045179-b69d-4414-ad16-ec8c3e9d1940.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_17%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png">如上图所示，A 高于阈值 maxVal 所以是真正的边界点，C 虽然低于 maxVal 但高于 minVal 并且与 A 相连，所以也被认为是真正的边界点。而 B 就会被抛弃，因为低于 maxVal 而且不与真正的边界点相连。所以选择合适的 maxVal 和 minVal 对于能否得到好的结果非常重要。</p>
<h4 id="8-4-2-应用"><a href="#8-4-2-应用" class="headerlink" title="8.4.2 应用"></a>8.4.2 应用</h4><p>在 OpenCV 中要实现 Canny 检测使用的 API:</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python">canny <span class="token operator">=</span> cv<span class="token punctuation">.</span>Canny<span class="token punctuation">(</span>image<span class="token punctuation">,</span> threshold1<span class="token punctuation">,</span> threshold2<span class="token punctuation">)</span>
  image<span class="token punctuation">:</span>灰度图
  threshold1<span class="token punctuation">:</span> minval，较小的阈值将间断的边缘连接起来
  threshold2<span class="token punctuation">:</span> maxval，较大的阈值检测图像中明显的边缘<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span></span></code></pre></div>
<p>示例：</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token keyword">import</span> cv2 <span class="token keyword">as</span> cv
<span class="token keyword">import</span> numpy <span class="token keyword">as</span> np
<span class="token keyword">from</span> matplotlib <span class="token keyword">import</span> pyplot <span class="token keyword">as</span> plt

<span class="token comment"># 1 图像读取</span>
img <span class="token operator">=</span> cv<span class="token punctuation">.</span>imread<span class="token punctuation">(</span><span class="token string">'./image/horse.jpg'</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span>
<span class="token comment"># 2 Canny边缘检测</span>
lowThreshold <span class="token operator">=</span> <span class="token number">0</span>
max_lowThreshold <span class="token operator">=</span> <span class="token number">100</span>
canny <span class="token operator">=</span> cv<span class="token punctuation">.</span>Canny<span class="token punctuation">(</span>img<span class="token punctuation">,</span> lowThreshold<span class="token punctuation">,</span> max_lowThreshold<span class="token punctuation">)</span>
<span class="token comment"># 3 图像展示</span>
plt<span class="token punctuation">.</span>figure<span class="token punctuation">(</span>figsize<span class="token operator">=</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">,</span> <span class="token number">8</span><span class="token punctuation">)</span><span class="token punctuation">,</span> dpi<span class="token operator">=</span><span class="token number">100</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>subplot<span class="token punctuation">(</span><span class="token number">121</span><span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>imshow<span class="token punctuation">(</span>img<span class="token punctuation">,</span> cmap<span class="token operator">=</span>plt<span class="token punctuation">.</span>cm<span class="token punctuation">.</span>gray<span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>title<span class="token punctuation">(</span><span class="token string">'原图'</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>xticks<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>yticks<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>subplot<span class="token punctuation">(</span><span class="token number">122</span><span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>imshow<span class="token punctuation">(</span>canny<span class="token punctuation">,</span> cmap<span class="token operator">=</span>plt<span class="token punctuation">.</span>cm<span class="token punctuation">.</span>gray<span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>title<span class="token punctuation">(</span><span class="token string">'Canny检测后结果'</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>xticks<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>yticks<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>show<span class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617376885925-6f7de64d-2e84-49d4-9b47-bac864590aff.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_22%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png"></p>
<h2 id="9-模版匹配和霍夫变换"><a href="#9-模版匹配和霍夫变换" class="headerlink" title="9. 模版匹配和霍夫变换"></a>9. 模版匹配和霍夫变换</h2><h3 id="9-1-模板匹配"><a href="#9-1-模板匹配" class="headerlink" title="9.1 模板匹配"></a>9.1 模板匹配</h3><h4 id="9-1-1-原理"><a href="#9-1-1-原理" class="headerlink" title="9.1.1 原理"></a>9.1.1 原理</h4><p>所谓的模板匹配，就是在给定的图片中查找和模板最相似的区域，该算法的输入包括模板和图片，整个任务的思路就是按照滑窗的思路不断的移动模板图片，计算其与图像中对应区域的匹配度，最终将匹配度最高的区域选择为最终的结果。<br><strong>实现流程：</strong></p>
<ul>
<li>准备两幅图像： 1.原图像(I)：在这幅图中，找到与模板相匹配的区域 2.模板(T)：与原图像进行比对的图像块<br><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617377677931-6e3c17cf-26c5-4156-a6b0-b819e68aa492.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_12%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10#height=149&amp;id=IFkQw&amp;margin=%5Bobject%20Object%5D&amp;name=image.png&amp;originHeight=149&amp;originWidth=422&amp;originalType=binary∶=1&amp;size=150362&amp;status=done&amp;style=none&amp;width=422" srcset="/img/loading.gif" lazyload alt="image.png"></li>
<li>滑动模板图像和原图像进行比对：</li>
</ul>
<p><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617377673251-4f53ff68-42ab-4e1b-a070-ed608a3e7476.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_14%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png">将模板块每次移动一个像素 (从左往右，从上往下)，在每一个位置，都计算与模板图像的相似程度。</p>
<ul>
<li>对于每一个位置将计算的相似结果保存在结果矩阵（R）中。如果输入图像的大小（WxH）且模板图像的大小(wxh)，则输出矩阵 R 的大小为（W-w + 1,H-h + 1）将 R 显示为图像，如下图所示：</li>
</ul>
<p><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617377667733-aa5a1cb9-e1f2-4b3d-8db6-a86c2a4c952c.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_14%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png"></p>
<ul>
<li>获得上述图像后，查找最大值所在的位置，那么该位置对应的区域就被认为是最匹配的。对应的区域就是以该点为顶点，长宽和模板图像一样大小的矩阵。</li>
</ul>
<h4 id="9-1-2-实现"><a href="#9-1-2-实现" class="headerlink" title="9.1.2 实现"></a>9.1.2 实现</h4><p>我们使用 OpenCV 中的方法实现模板匹配。<br>API：</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python">res <span class="token operator">=</span> cv<span class="token punctuation">.</span>matchTemplate<span class="token punctuation">(</span>img<span class="token punctuation">,</span>template<span class="token punctuation">,</span>method<span class="token punctuation">)</span>
  img<span class="token punctuation">:</span> 要进行模板匹配的图像
  Template ：模板
  method：实现模板匹配的算法，主要有：
  a<span class="token punctuation">.</span> 平方差匹配<span class="token punctuation">(</span>CV_TM_SQDIFF<span class="token punctuation">)</span>：利用模板与图像之间的平方差进行匹配，最好的匹配是<span class="token number">0</span>，匹配越差，匹配的值越大。
  b<span class="token punctuation">.</span> 相关匹配<span class="token punctuation">(</span>CV_TM_CCORR<span class="token punctuation">)</span>：利用模板与图像间的乘法进行匹配，数值越大表示匹配程度较高，越小表示匹配效果差。
  c<span class="token punctuation">.</span> 利用相关系数匹配<span class="token punctuation">(</span>CV_TM_CCOEFF<span class="token punctuation">)</span>：利用模板与图像间的相关系数匹配，<span class="token number">1</span>表示完美的匹配，<span class="token operator">-</span><span class="token number">1</span>表示最差的匹配。
  完成匹配后，使用cv<span class="token punctuation">.</span>minMaxLoc<span class="token punctuation">(</span><span class="token punctuation">)</span>方法查找最大值所在的位置即可。如果使用平方差作为比较方法，则最小值位置是最佳匹配位置。<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p><strong>示例：</strong><br>在该案例中，载入要搜索的图像和模板，图像如下所示：<br><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617377637806-0d0ce97a-04d1-4012-b564-d677da0f4e9d.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_16%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png">模板如下所示：<br><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617377632803-a9d606a9-0035-4d08-8ee9-b0dc630300eb.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_9%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png">通过 matchTemplate 实现模板匹配，使用 minMaxLoc 定位最匹配的区域，并用矩形标注最匹配的区域。</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token keyword">import</span> cv2 <span class="token keyword">as</span> cv
<span class="token keyword">import</span> numpy <span class="token keyword">as</span> np
<span class="token keyword">from</span> matplotlib <span class="token keyword">import</span> pyplot <span class="token keyword">as</span> plt

<span class="token comment"># 1 图像和模板读取</span>
img <span class="token operator">=</span> cv<span class="token punctuation">.</span>imread<span class="token punctuation">(</span><span class="token string">'./image/wulin2.jpeg'</span><span class="token punctuation">)</span>
template <span class="token operator">=</span> cv<span class="token punctuation">.</span>imread<span class="token punctuation">(</span><span class="token string">'./image/wulin.jpeg'</span><span class="token punctuation">)</span>
h<span class="token punctuation">,</span> w<span class="token punctuation">,</span> l <span class="token operator">=</span> template<span class="token punctuation">.</span>shape
<span class="token comment"># 2 模板匹配</span>
<span class="token comment"># 2.1 模板匹配</span>
res <span class="token operator">=</span> cv<span class="token punctuation">.</span>matchTemplate<span class="token punctuation">(</span>img<span class="token punctuation">,</span> template<span class="token punctuation">,</span> cv<span class="token punctuation">.</span>TM_CCORR<span class="token punctuation">)</span>
<span class="token comment"># 2.2 返回图像中最匹配的位置，确定左上角的坐标，并将匹配位置绘制在图像上</span>
min_val<span class="token punctuation">,</span> max_val<span class="token punctuation">,</span> min_loc<span class="token punctuation">,</span> max_loc <span class="token operator">=</span> cv<span class="token punctuation">.</span>minMaxLoc<span class="token punctuation">(</span>res<span class="token punctuation">)</span>
<span class="token comment"># 使用平方差时最小值为最佳匹配位置</span>
<span class="token comment"># top_left = min_loc</span>
top_left <span class="token operator">=</span> max_loc
bottom_right <span class="token operator">=</span> <span class="token punctuation">(</span>top_left<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator">+</span> w<span class="token punctuation">,</span> top_left<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span> <span class="token operator">+</span> h<span class="token punctuation">)</span>
cv<span class="token punctuation">.</span>rectangle<span class="token punctuation">(</span>img<span class="token punctuation">,</span> top_left<span class="token punctuation">,</span> bottom_right<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">255</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">)</span>
<span class="token comment"># 3 图像显示</span>
plt<span class="token punctuation">.</span>imshow<span class="token punctuation">(</span>img<span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token punctuation">,</span> <span class="token punctuation">:</span><span class="token punctuation">,</span> <span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>title<span class="token punctuation">(</span><span class="token string">'匹配结果'</span><span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>xticks<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>yticks<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>show<span class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617377621291-350eab8c-3516-45a7-8001-733004b201e4.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_19%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png">拓展：模板匹配不适用于尺度变换，视角变换后的图像，这时我们就要使用关键点匹配算法，比较经典的关键点检测算法包括 SIFT 和 SURF 等，主要的思路是首先通过关键点检测算法获取模板和测试图片中的关键点；然后使用关键点匹配算法处理即可，这些关键点可以很好的处理尺度变化、视角变换、旋转变化、光照变化等，具有很好的不变性。</p>
<h3 id="9-2-霍夫变换"><a href="#9-2-霍夫变换" class="headerlink" title="9.2 霍夫变换"></a>9.2 霍夫变换</h3><p>霍夫变换常用来提取图像中的直线和圆等几何形状，如下图所示：<br><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617377611899-bfd17796-4839-4f21-82de-f28bab27aff3.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_22%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png"></p>
<h4 id="9-2-1-霍夫线检测"><a href="#9-2-1-霍夫线检测" class="headerlink" title="9.2.1 霍夫线检测"></a>9.2.1 霍夫线检测</h4><p>在 OpenCV 中做霍夫线检测是使用的 API 是：</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python">cv<span class="token punctuation">.</span>HoughLines<span class="token punctuation">(</span>img<span class="token punctuation">,</span> rho<span class="token punctuation">,</span> theta<span class="token punctuation">,</span> threshold<span class="token punctuation">)</span>
  img<span class="token punctuation">:</span> 检测的图像，要求是二值化的图像，所以在调用霍夫变换之前首先要进行二值化，或者进行Canny边缘检测
  rho、theta<span class="token punctuation">:</span> \rhoρ 和\thetaθ的精确度
  threshold<span class="token punctuation">:</span> 阈值，只有累加器中的值高于该阈值时才被认为是直线。<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span></span></code></pre></div>
<p>霍夫线检测的整个流程如下图所示，这是在 stackflow 上一个关于霍夫线变换的解释：<br><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617377535308-7771b36c-d3dc-4cfc-94d4-18de2b68287d.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_21%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png"><strong>示例：</strong><br>检测下述图像中的直线：<br><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617377528808-ae67a32f-4daf-47e9-ac08-fbadc061a003.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_15%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png"><br><div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token keyword">import</span> numpy <span class="token keyword">as</span> np
<span class="token keyword">import</span> random
<span class="token keyword">import</span> cv2 <span class="token keyword">as</span> cv
<span class="token keyword">import</span> matplotlib<span class="token punctuation">.</span>pyplot <span class="token keyword">as</span> plt

<span class="token comment"># 1.加载图片，转为二值图</span>
img <span class="token operator">=</span> cv<span class="token punctuation">.</span>imread<span class="token punctuation">(</span><span class="token string">'./image/rili.jpg'</span><span class="token punctuation">)</span>
gray <span class="token operator">=</span> cv<span class="token punctuation">.</span>cvtColor<span class="token punctuation">(</span>img<span class="token punctuation">,</span> cv<span class="token punctuation">.</span>COLOR_BGR2GRAY<span class="token punctuation">)</span>
edges <span class="token operator">=</span> cv<span class="token punctuation">.</span>Canny<span class="token punctuation">(</span>gray<span class="token punctuation">,</span> <span class="token number">50</span><span class="token punctuation">,</span> <span class="token number">150</span><span class="token punctuation">)</span>
<span class="token comment"># 2.霍夫直线变换</span>
lines <span class="token operator">=</span> cv<span class="token punctuation">.</span>HoughLines<span class="token punctuation">(</span>edges<span class="token punctuation">,</span> <span class="token number">0.8</span><span class="token punctuation">,</span> np<span class="token punctuation">.</span>pi <span class="token operator">/</span> <span class="token number">180</span><span class="token punctuation">,</span> <span class="token number">150</span><span class="token punctuation">)</span>
<span class="token comment"># 3.将检测的线绘制在图像上（注意是极坐标噢）</span>
<span class="token keyword">for</span> line <span class="token keyword">in</span> lines<span class="token punctuation">:</span>
    rho<span class="token punctuation">,</span> theta <span class="token operator">=</span> line<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span>
    a <span class="token operator">=</span> np<span class="token punctuation">.</span>cos<span class="token punctuation">(</span>theta<span class="token punctuation">)</span>
    b <span class="token operator">=</span> np<span class="token punctuation">.</span>sin<span class="token punctuation">(</span>theta<span class="token punctuation">)</span>
    x0 <span class="token operator">=</span> a <span class="token operator">*</span> rho
    y0 <span class="token operator">=</span> b <span class="token operator">*</span> rho
    x1 <span class="token operator">=</span> <span class="token builtin">int</span><span class="token punctuation">(</span>x0 <span class="token operator">+</span> <span class="token number">1000</span> <span class="token operator">*</span> <span class="token punctuation">(</span><span class="token operator">-</span>b<span class="token punctuation">)</span><span class="token punctuation">)</span>
    y1 <span class="token operator">=</span> <span class="token builtin">int</span><span class="token punctuation">(</span>y0 <span class="token operator">+</span> <span class="token number">1000</span> <span class="token operator">*</span> <span class="token punctuation">(</span>a<span class="token punctuation">)</span><span class="token punctuation">)</span>
    x2 <span class="token operator">=</span> <span class="token builtin">int</span><span class="token punctuation">(</span>x0 <span class="token operator">-</span> <span class="token number">1000</span> <span class="token operator">*</span> <span class="token punctuation">(</span><span class="token operator">-</span>b<span class="token punctuation">)</span><span class="token punctuation">)</span>
    y2 <span class="token operator">=</span> <span class="token builtin">int</span><span class="token punctuation">(</span>y0 <span class="token operator">-</span> <span class="token number">1000</span> <span class="token operator">*</span> <span class="token punctuation">(</span>a<span class="token punctuation">)</span><span class="token punctuation">)</span>
    cv<span class="token punctuation">.</span>line<span class="token punctuation">(</span>img<span class="token punctuation">,</span> <span class="token punctuation">(</span>x1<span class="token punctuation">,</span> y1<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">(</span>x2<span class="token punctuation">,</span> y2<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">255</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token comment"># 4. 图像显示</span>
plt<span class="token punctuation">.</span>figure<span class="token punctuation">(</span>figsize<span class="token operator">=</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">,</span> <span class="token number">8</span><span class="token punctuation">)</span><span class="token punctuation">,</span> dpi<span class="token operator">=</span><span class="token number">100</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>imshow<span class="token punctuation">(</span>img<span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token punctuation">,</span> <span class="token punctuation">:</span><span class="token punctuation">,</span> <span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>title<span class="token punctuation">(</span><span class="token string">'霍夫变换线检测'</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>xticks<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>yticks<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>show<span class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div></p>
<p><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617377847178-1e513072-e10b-4e7a-abb1-11fbd68ed1cd.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_20%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png"></p>
<h4 id="9-2-2-霍夫圆检测-了解"><a href="#9-2-2-霍夫圆检测-了解" class="headerlink" title="9.2.2 霍夫圆检测[了解]"></a>9.2.2 霍夫圆检测[了解]</h4><ol>
<li>原理圆的表示式是：</li>
</ol>
<p><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617377489138-a6315a35-5c2e-47db-8a3e-6cc76a530795.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_10%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png">其中 a<em>a</em>和 b<em>b</em>表示圆心坐标，r<em>r</em>表示圆半径，因此标准的霍夫圆检测就是在这三个参数组成的三维空间累加器上进行圆形检测，此时效率就会很低，所以 OpenCV 中使用<strong>霍夫梯度法</strong>进行圆形的检测。霍夫梯度法将霍夫圆检测范围两个阶段，第一阶段检测圆心，第二阶段利用圆心推导出圆半径。</p>
<ul>
<li>圆心检测的原理：圆心是圆周法线的交汇处，设置一个阈值，在某点的相交的直线的条数大于这个阈值就认为该交汇点为圆心。</li>
<li>圆半径确定原理：圆心到圆周上的距离（半径）是相同的，确定一个阈值，只要相同距离的数量大于该阈值，就认为该距离是该圆心的半径。</li>
</ul>
<p>原则上霍夫变换可以检测任何形状，但复杂的形状需要的参数就多，霍夫空间的维数就多，因此在程序实现上所需的内存空间以及运行效率上都不利于把标准霍夫变换应用于实际复杂图形的检测中。霍夫梯度法是霍夫变换的改进，它的目的是减小霍夫空间的维度，提高效率。<br>API 在 OpenCV 中检测图像中的圆环使用的是 API 是：</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python">circles <span class="token operator">=</span> cv<span class="token punctuation">.</span>HoughCircles<span class="token punctuation">(</span>image<span class="token punctuation">,</span> method<span class="token punctuation">,</span> dp<span class="token punctuation">,</span> minDist<span class="token punctuation">,</span> param1<span class="token operator">=</span><span class="token number">100</span><span class="token punctuation">,</span> param2<span class="token operator">=</span><span class="token number">100</span><span class="token punctuation">,</span> minRadius<span class="token operator">=</span><span class="token number">0</span><span class="token punctuation">,</span>maxRadius<span class="token operator">=</span><span class="token number">0</span> <span class="token punctuation">)</span>
  image：输入图像，应输入灰度图像
  method：使用霍夫变换圆检测的算法，它的参数是CV_HOUGH_GRADIENT
  dp：霍夫空间的分辨率，dp<span class="token operator">=</span><span class="token number">1</span>时表示霍夫空间与输入图像空间的大小一致，dp<span class="token operator">=</span><span class="token number">2</span>时霍夫空间是输入图像空间的一半，以此类推
  minDist为圆心之间的最小距离，如果检测到的两个圆心之间距离小于该值，则认为它们是同一个圆心
  param1：边缘检测时使用Canny算子的高阈值，低阈值是高阈值的一半。
  param2：检测圆心和确定半径时所共有的阈值
  minRadius和maxRadius为所检测到的圆半径的最小值和最大值<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p>返回：</p>
<ul>
<li>circles：输出圆向量，包括三个浮点型的元素——圆心横坐标，圆心纵坐标和圆半径</li>
</ul>
<p>由于霍夫圆检测对噪声比较敏感，所以首先对图像进行中值滤波。</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token keyword">import</span> cv2 <span class="token keyword">as</span> cv
<span class="token keyword">import</span> numpy <span class="token keyword">as</span> np
<span class="token keyword">import</span> matplotlib<span class="token punctuation">.</span>pyplot <span class="token keyword">as</span> plt

<span class="token comment"># 1 读取图像，并转换为灰度图</span>
planets <span class="token operator">=</span> cv<span class="token punctuation">.</span>imread<span class="token punctuation">(</span><span class="token string">"./image/star.jpeg"</span><span class="token punctuation">)</span>
gay_img <span class="token operator">=</span> cv<span class="token punctuation">.</span>cvtColor<span class="token punctuation">(</span>planets<span class="token punctuation">,</span> cv<span class="token punctuation">.</span>COLOR_BGRA2GRAY<span class="token punctuation">)</span>
<span class="token comment"># 2 进行中值模糊，去噪点</span>
img <span class="token operator">=</span> cv<span class="token punctuation">.</span>medianBlur<span class="token punctuation">(</span>gay_img<span class="token punctuation">,</span> <span class="token number">7</span><span class="token punctuation">)</span>
<span class="token comment"># 3 霍夫圆检测</span>
circles <span class="token operator">=</span> cv<span class="token punctuation">.</span>HoughCircles<span class="token punctuation">(</span>img<span class="token punctuation">,</span> cv<span class="token punctuation">.</span>HOUGH_GRADIENT<span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">200</span><span class="token punctuation">,</span> param1<span class="token operator">=</span><span class="token number">100</span><span class="token punctuation">,</span> param2<span class="token operator">=</span><span class="token number">30</span><span class="token punctuation">,</span> minRadius<span class="token operator">=</span><span class="token number">0</span><span class="token punctuation">,</span> maxRadius<span class="token operator">=</span><span class="token number">100</span><span class="token punctuation">)</span>
<span class="token comment"># 4 将检测结果绘制在图像上</span>
<span class="token keyword">for</span> i <span class="token keyword">in</span> circles<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token punctuation">:</span><span class="token punctuation">]</span><span class="token punctuation">:</span>  <span class="token comment"># 遍历矩阵每一行的数据</span>
    <span class="token comment"># 绘制圆形</span>
    cv<span class="token punctuation">.</span>circle<span class="token punctuation">(</span>planets<span class="token punctuation">,</span> <span class="token punctuation">(</span>i<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">,</span> i<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">,</span> i<span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">255</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">)</span>
    <span class="token comment"># 绘制圆心</span>
    cv<span class="token punctuation">.</span>circle<span class="token punctuation">(</span>planets<span class="token punctuation">,</span> <span class="token punctuation">(</span>i<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">,</span> i<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">255</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">)</span>
<span class="token comment"># 5 图像显示</span>
plt<span class="token punctuation">.</span>figure<span class="token punctuation">(</span>figsize<span class="token operator">=</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">,</span> <span class="token number">8</span><span class="token punctuation">)</span><span class="token punctuation">,</span> dpi<span class="token operator">=</span><span class="token number">100</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>imshow<span class="token punctuation">(</span>planets<span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token punctuation">,</span> <span class="token punctuation">:</span><span class="token punctuation">,</span> <span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>title<span class="token punctuation">(</span><span class="token string">'霍夫变换圆检测'</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>xticks<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">,</span> plt<span class="token punctuation">.</span>yticks<span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
plt<span class="token punctuation">.</span>show<span class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617377436506-2c5f0412-f673-47ec-9648-ba6b65b2383c.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_21%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png"></p>
<h2 id="10-视频操作"><a href="#10-视频操作" class="headerlink" title="10. 视频操作"></a>10. 视频操作</h2><h3 id="10-1-视频读写"><a href="#10-1-视频读写" class="headerlink" title="10.1 视频读写"></a>10.1 视频读写</h3><h4 id="10-1-1-从文件中读取视频并播放"><a href="#10-1-1-从文件中读取视频并播放" class="headerlink" title="10.1.1 从文件中读取视频并播放"></a>10.1.1 从文件中读取视频并播放</h4><p>在 OpenCV 中我们要获取一个视频，需要创建一个 VideoCapture 对象，指定你要读取的视频文件：</p>
<ol>
<li>创建读取视频的对象</li>
</ol>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python">cap <span class="token operator">=</span> cv<span class="token punctuation">.</span>VideoCapture<span class="token punctuation">(</span>filepath<span class="token punctuation">)</span>
    filepath<span class="token punctuation">:</span> 视频文件路径<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre></div>
<p>视频的属性信息 2.1. 获取视频的某些属性，</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python">retval <span class="token operator">=</span> cap<span class="token punctuation">.</span>get<span class="token punctuation">(</span>propId<span class="token punctuation">)</span>
  propId<span class="token punctuation">:</span> 从<span class="token number">0</span>到<span class="token number">18</span>的数字，每个数字表示视频的属性<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span></span></code></pre></div>
<p>常用属性有：<br><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617378066912-406b06cc-fbac-4afd-8bdb-ef88de756e78.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_20%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png">修改视频的属性信息</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python">cap<span class="token punctuation">.</span><span class="token builtin">set</span><span class="token punctuation">(</span>propId，value<span class="token punctuation">)</span>
  proid<span class="token punctuation">:</span> 属性的索引，与上面的表格相对应
  value<span class="token punctuation">:</span> 修改后的属性值<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code></pre></div>
<p>判断图像是否读取成功</p>
<div class="code-wrapper"><pre class="line-numbers language-none"><code class="language-none">isornot &#x3D; cap.isOpened()<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre></div>
<ul>
<li>若读取成功则返回 true，否则返回 False</li>
</ul>
<p>获取视频的一帧图像</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python">ret<span class="token punctuation">,</span> frame <span class="token operator">=</span> cap<span class="token punctuation">.</span>read<span class="token punctuation">(</span><span class="token punctuation">)</span>
  ret<span class="token punctuation">:</span> 若获取成功返回<span class="token boolean">True</span>，获取失败，返回<span class="token boolean">False</span>
  Frame<span class="token punctuation">:</span> 获取到的某一帧的图像<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code></pre></div>
<ol>
<li>调用 cv.imshow()显示图像，在显示图像时使用 cv.waitkey()设置适当的持续时间，如果太低视频会播放的非常快，如果太高就会播放的非常慢，通常情况下我们设置 25ms 就可以了。</li>
<li>最后，调用 cap.realease()将视频释放掉</li>
</ol>
<p>示例：</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token keyword">import</span> numpy <span class="token keyword">as</span> np
<span class="token keyword">import</span> cv2 <span class="token keyword">as</span> cv

<span class="token comment"># 1.获取视频对象</span>
cap <span class="token operator">=</span> cv<span class="token punctuation">.</span>VideoCapture<span class="token punctuation">(</span><span class="token string">'./image/DOG.wmv'</span><span class="token punctuation">)</span>
<span class="token comment"># 2.判断是否读取成功</span>
<span class="token keyword">while</span> <span class="token punctuation">(</span>cap<span class="token punctuation">.</span>isOpened<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token comment"># 3.获取每一帧图像</span>
    ret<span class="token punctuation">,</span> frame <span class="token operator">=</span> cap<span class="token punctuation">.</span>read<span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token comment"># 4. 获取成功显示图像</span>
    <span class="token keyword">if</span> ret <span class="token operator">==</span> <span class="token boolean">True</span><span class="token punctuation">:</span>
        cv<span class="token punctuation">.</span>imshow<span class="token punctuation">(</span><span class="token string">'frame'</span><span class="token punctuation">,</span> frame<span class="token punctuation">)</span>
    <span class="token comment"># 5.每一帧间隔为25ms</span>
    <span class="token keyword">if</span> cv<span class="token punctuation">.</span>waitKey<span class="token punctuation">(</span><span class="token number">25</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span> <span class="token number">0xFF</span> <span class="token operator">==</span> <span class="token builtin">ord</span><span class="token punctuation">(</span><span class="token string">'q'</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
        <span class="token keyword">break</span>
<span class="token comment"># 6.释放视频对象</span>
cap<span class="token punctuation">.</span>release<span class="token punctuation">(</span><span class="token punctuation">)</span>
cv<span class="token punctuation">.</span>destoryAllwindows<span class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617378222014-ef2ddd85-a472-4d8f-bac1-ed9bfed8aff7.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_13%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png"></p>
<h4 id="10-1-2-保存视频"><a href="#10-1-2-保存视频" class="headerlink" title="10.1.2 保存视频"></a>10.1.2 保存视频</h4><p>在 OpenCV 中我们保存视频使用的是 VedioWriter 对象，在其中指定输出文件的名称，如下所示：</p>
<ol>
<li>创建视频写入的对象</li>
</ol>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python">out <span class="token operator">=</span> cv<span class="token punctuation">.</span>VideoWriter<span class="token punctuation">(</span>filename<span class="token punctuation">,</span>fourcc<span class="token punctuation">,</span> fps<span class="token punctuation">,</span> frameSize<span class="token punctuation">)</span>
    filename：视频保存的位置
    fourcc：指定视频编解码器的<span class="token number">4</span>字节代码
    fps：帧率
    frameSize：帧大小<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p>设置视频的编解码器，如下所示，</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python">retval <span class="token operator">=</span> cv<span class="token punctuation">.</span>VideoWriter_fourcc<span class="token punctuation">(</span> c1<span class="token punctuation">,</span> c2<span class="token punctuation">,</span> c3<span class="token punctuation">,</span> c4 <span class="token punctuation">)</span>
  c1<span class="token punctuation">,</span>c2<span class="token punctuation">,</span>c3<span class="token punctuation">,</span>c4<span class="token punctuation">:</span> 是视频编解码器的<span class="token number">4</span>字节代码，在fourcc<span class="token punctuation">.</span>org中找到可用代码列表，与平台紧密相关，常用的有：
  在Windows中：DIVX（<span class="token punctuation">.</span>avi）
  在OS中：MJPG（<span class="token punctuation">.</span>mp4），DIVX（<span class="token punctuation">.</span>avi），X264（<span class="token punctuation">.</span>mkv）<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span></span></code></pre></div>
<ul>
<li>利用 cap.read()获取视频中的每一帧图像，并使用 out.write()将某一帧图像写入视频中。</li>
<li>使用 cap.release()和 out.release()释放资源。</li>
</ul>
<p>示例：</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token keyword">import</span> cv2 <span class="token keyword">as</span> cv
<span class="token keyword">import</span> numpy <span class="token keyword">as</span> np

<span class="token comment"># 1. 读取视频</span>
cap <span class="token operator">=</span> cv<span class="token punctuation">.</span>VideoCapture<span class="token punctuation">(</span><span class="token string">"./image/DOG.wmv"</span><span class="token punctuation">)</span>
<span class="token comment"># 2. 获取图像的属性（宽和高，）,并将其转换为整数</span>
frame_width <span class="token operator">=</span> <span class="token builtin">int</span><span class="token punctuation">(</span>cap<span class="token punctuation">.</span>get<span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
frame_height <span class="token operator">=</span> <span class="token builtin">int</span><span class="token punctuation">(</span>cap<span class="token punctuation">.</span>get<span class="token punctuation">(</span><span class="token number">4</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token comment"># 3. 创建保存视频的对象，设置编码格式，帧率，图像的宽高等</span>
out <span class="token operator">=</span> cv<span class="token punctuation">.</span>VideoWriter<span class="token punctuation">(</span><span class="token string">'outpy.avi'</span><span class="token punctuation">,</span> cv<span class="token punctuation">.</span>VideoWriter_fourcc<span class="token punctuation">(</span><span class="token string">'M'</span><span class="token punctuation">,</span> <span class="token string">'J'</span><span class="token punctuation">,</span> <span class="token string">'P'</span><span class="token punctuation">,</span> <span class="token string">'G'</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">,</span> <span class="token punctuation">(</span>frame_width<span class="token punctuation">,</span> frame_height<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token keyword">while</span> <span class="token punctuation">(</span><span class="token boolean">True</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token comment"># 4.获取视频中的每一帧图像</span>
    ret<span class="token punctuation">,</span> frame <span class="token operator">=</span> cap<span class="token punctuation">.</span>read<span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token keyword">if</span> ret <span class="token operator">==</span> <span class="token boolean">True</span><span class="token punctuation">:</span>
        <span class="token comment"># 5.将每一帧图像写入到输出文件中</span>
        out<span class="token punctuation">.</span>write<span class="token punctuation">(</span>frame<span class="token punctuation">)</span>
    <span class="token keyword">else</span><span class="token punctuation">:</span>
        <span class="token keyword">break</span>
    <span class="token comment"># 6.释放资源</span>
cap<span class="token punctuation">.</span>release<span class="token punctuation">(</span><span class="token punctuation">)</span>
out<span class="token punctuation">.</span>release<span class="token punctuation">(</span><span class="token punctuation">)</span>
cv<span class="token punctuation">.</span>destroyAllWindows<span class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<h3 id="10-2-视频追踪"><a href="#10-2-视频追踪" class="headerlink" title="10.2 视频追踪"></a>10.2 视频追踪</h3><h4 id="10-2-1-meanshift"><a href="#10-2-1-meanshift" class="headerlink" title="10.2.1.meanshift"></a>10.2.1.meanshift</h4><p>原理<br>meanshift 算法的原理很简单。假设你有一堆点集，还有一个小的窗口，这个窗口可能是圆形的，现在你可能要移动这个窗口到点集密度最大的区域当中。<br>如下图：<br><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617378507131-8a1f983c-1458-451b-8692-dc52ee0e1748.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_13%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png">最开始的窗口是蓝色圆环的区域，命名为 C1。蓝色圆环的圆心用一个蓝色的矩形标注，命名为 C1_o。<br>而窗口中所有点的点集构成的质心在蓝色圆形点 C1_r 处，显然圆环的形心和质心并不重合。所以，移动蓝色的窗口，使得形心与之前得到的质心重合。在新移动后的圆环的区域当中再次寻找圆环当中所包围点集的质心，然后再次移动，通常情况下，形心和质心是不重合的。不断执行上面的移动过程，直到形心和质心大致重合结束。 这样，最后圆形的窗口会落到像素分布最大的地方，也就是图中的绿色圈，命名为 C2。<br>meanshift 算法除了应用在视频追踪当中，在聚类，平滑等等各种涉及到数据以及非监督学习的场合当中均有重要应用，是一个应用广泛的算法。<br>图像是一个矩阵信息，如何在一个视频当中使用 meanshift 算法来追踪一个运动的物体呢？ 大致流程如下：</p>
<ol>
<li>首先在图像上选定一个目标区域</li>
<li>计算选定区域的直方图分布，一般是 HSV 色彩空间的直方图。</li>
<li>对下一帧图像 b 同样计算直方图分布。</li>
<li>计算图像 b 当中与选定区域直方图分布最为相似的区域，使用 meanshift 算法将选定区域沿着最为相似的部分进行移动，直到找到最相似的区域，便完成了在图像 b 中的目标追踪。</li>
<li>重复 3 到 4 的过程，就完成整个视频目标追踪。<br>通常情况下我们使用直方图反向投影得到的图像和第一帧目标对象的起始位置，当目标对象的移动会反映到直方图反向投影图中，meanshift 算法就把我们的窗口移动到反向投影图像中灰度密度最大的区域了。如下图所示：</li>
</ol>
<p><img src="https://cdn.nlark.com/yuque/0/2021/gif/448115/1617378497427-d75bfef1-ef0a-4ae0-a1cd-5d5384e25270.gif#height=283&amp;id=ZkoqE&amp;margin=%5Bobject%20Object%5D&amp;name=image2-0785334.gif&amp;originHeight=283&amp;originWidth=212&amp;originalType=binary∶=1&amp;size=180533&amp;status=done&amp;style=none&amp;width=212" srcset="/img/loading.gif" lazyload alt="image2-0785334.gif"><br>直方图反向投影的流程是：<br>假设我们有一张 100x100 的输入图像，有一张 10x10 的模板图像，查找的过程是这样的：</p>
<ol>
<li>从输入图像的左上角(0,0)开始，切割一块(0,0)至(10,10)的临时图像；</li>
<li>生成临时图像的直方图；</li>
<li>用临时图像的直方图和模板图像的直方图对比，对比结果记为 c；</li>
<li>直方图对比结果 c，就是结果图像(0,0)处的像素值；</li>
<li>切割输入图像从(0,1)至(10,11)的临时图像，对比直方图，并记录到结果图像；</li>
<li>重复 1 ～ 5 步直到输入图像的右下角，就形成了直方图的反向投影。</li>
</ol>
<p><strong>实现</strong><br>在 OpenCV 中实现 Meanshift 的 API 是：</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python">cv<span class="token punctuation">.</span>meanShift<span class="token punctuation">(</span>probImage<span class="token punctuation">,</span> window<span class="token punctuation">,</span> criteria<span class="token punctuation">)</span>
  probImage<span class="token punctuation">:</span> ROI区域，即目标的直方图的反向投影
  window： 初始搜索窗口，就是定义ROI的rect
  criteria<span class="token punctuation">:</span> 确定窗口搜索停止的准则，主要有迭代次数达到设置的最大值，窗口中心的漂移值大于某个设定的限值等。<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span></span></code></pre></div>
<p>实现 Meanshift 的主要流程是：</p>
<ol>
<li>读取视频文件：cv.videoCapture()</li>
<li>感兴趣区域设置：获取第一帧图像，并设置目标区域，即感兴趣区域</li>
<li>计算直方图：计算感兴趣区域的 HSV 直方图，并进行归一化</li>
<li>目标追踪：设置窗口搜索停止条件，直方图反向投影，进行目标追踪，并在目标位置绘制矩形框。</li>
</ol>
<p>示例：</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token keyword">import</span> numpy <span class="token keyword">as</span> np
<span class="token keyword">import</span> cv2 <span class="token keyword">as</span> cv

<span class="token comment"># 1.获取图像</span>
cap <span class="token operator">=</span> cv<span class="token punctuation">.</span>VideoCapture<span class="token punctuation">(</span><span class="token string">'./image/DOG.wmv'</span><span class="token punctuation">)</span>
<span class="token comment"># 2.获取第一帧图像，并指定目标位置</span>
ret<span class="token punctuation">,</span> frame <span class="token operator">=</span> cap<span class="token punctuation">.</span>read<span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token comment"># 2.1 目标位置（行，高，列，宽）</span>
r<span class="token punctuation">,</span> h<span class="token punctuation">,</span> c<span class="token punctuation">,</span> w <span class="token operator">=</span> <span class="token number">197</span><span class="token punctuation">,</span> <span class="token number">141</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">208</span>
track_window <span class="token operator">=</span> <span class="token punctuation">(</span>c<span class="token punctuation">,</span> r<span class="token punctuation">,</span> w<span class="token punctuation">,</span> h<span class="token punctuation">)</span>
<span class="token comment"># 2.2 指定目标的感兴趣区域</span>
roi <span class="token operator">=</span> frame<span class="token punctuation">[</span>r<span class="token punctuation">:</span>r <span class="token operator">+</span> h<span class="token punctuation">,</span> c<span class="token punctuation">:</span>c <span class="token operator">+</span> w<span class="token punctuation">]</span>
<span class="token comment"># 3. 计算直方图</span>
<span class="token comment"># 3.1 转换色彩空间（HSV）</span>
hsv_roi <span class="token operator">=</span> cv<span class="token punctuation">.</span>cvtColor<span class="token punctuation">(</span>roi<span class="token punctuation">,</span> cv<span class="token punctuation">.</span>COLOR_BGR2HSV<span class="token punctuation">)</span>
<span class="token comment"># 3.2 去除低亮度的值</span>
<span class="token comment"># mask = cv.inRange(hsv_roi, np.array((0., 60.,32.)), np.array((180.,255.,255.)))</span>
<span class="token comment"># 3.3 计算直方图</span>
roi_hist <span class="token operator">=</span> cv<span class="token punctuation">.</span>calcHist<span class="token punctuation">(</span><span class="token punctuation">[</span>hsv_roi<span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token boolean">None</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token number">180</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">180</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
<span class="token comment"># 3.4 归一化</span>
cv<span class="token punctuation">.</span>normalize<span class="token punctuation">(</span>roi_hist<span class="token punctuation">,</span> roi_hist<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">255</span><span class="token punctuation">,</span> cv<span class="token punctuation">.</span>NORM_MINMAX<span class="token punctuation">)</span>
<span class="token comment"># 4. 目标追踪</span>
<span class="token comment"># 4.1 设置窗口搜索终止条件：最大迭代次数，窗口中心漂移最小值</span>
term_crit <span class="token operator">=</span> <span class="token punctuation">(</span>cv<span class="token punctuation">.</span>TERM_CRITERIA_EPS <span class="token operator">|</span> cv<span class="token punctuation">.</span>TERM_CRITERIA_COUNT<span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span>
<span class="token keyword">while</span> <span class="token punctuation">(</span><span class="token boolean">True</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token comment"># 4.2 获取每一帧图像</span>
    ret<span class="token punctuation">,</span> frame <span class="token operator">=</span> cap<span class="token punctuation">.</span>read<span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token keyword">if</span> ret <span class="token operator">==</span> <span class="token boolean">True</span><span class="token punctuation">:</span>
        <span class="token comment"># 4.3 计算直方图的反向投影</span>
        hsv <span class="token operator">=</span> cv<span class="token punctuation">.</span>cvtColor<span class="token punctuation">(</span>frame<span class="token punctuation">,</span> cv<span class="token punctuation">.</span>COLOR_BGR2HSV<span class="token punctuation">)</span>
        dst <span class="token operator">=</span> cv<span class="token punctuation">.</span>calcBackProject<span class="token punctuation">(</span><span class="token punctuation">[</span>hsv<span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">,</span> roi_hist<span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">180</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span>
        <span class="token comment"># 4.4 进行meanshift追踪</span>
        ret<span class="token punctuation">,</span> track_window <span class="token operator">=</span> cv<span class="token punctuation">.</span>meanShift<span class="token punctuation">(</span>dst<span class="token punctuation">,</span> track_window<span class="token punctuation">,</span> term_crit<span class="token punctuation">)</span>
        <span class="token comment"># 4.5 将追踪的位置绘制在视频上，并进行显示</span>
        x<span class="token punctuation">,</span> y<span class="token punctuation">,</span> w<span class="token punctuation">,</span> h <span class="token operator">=</span> track_window
        img2 <span class="token operator">=</span> cv<span class="token punctuation">.</span>rectangle<span class="token punctuation">(</span>frame<span class="token punctuation">,</span> <span class="token punctuation">(</span>x<span class="token punctuation">,</span> y<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">(</span>x <span class="token operator">+</span> w<span class="token punctuation">,</span> y <span class="token operator">+</span> h<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token number">255</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">)</span>
        cv<span class="token punctuation">.</span>imshow<span class="token punctuation">(</span><span class="token string">'frame'</span><span class="token punctuation">,</span> img2<span class="token punctuation">)</span>
        <span class="token keyword">if</span> cv<span class="token punctuation">.</span>waitKey<span class="token punctuation">(</span><span class="token number">60</span><span class="token punctuation">)</span> <span class="token operator">&amp;</span> <span class="token number">0xFF</span> <span class="token operator">==</span> <span class="token builtin">ord</span><span class="token punctuation">(</span><span class="token string">'q'</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
            <span class="token keyword">break</span>
    <span class="token keyword">else</span><span class="token punctuation">:</span>
        <span class="token keyword">break</span>
<span class="token comment"># 5. 资源释放</span>
cap<span class="token punctuation">.</span>release<span class="token punctuation">(</span><span class="token punctuation">)</span>
cv<span class="token punctuation">.</span>destroyAllWindows<span class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p>下面是三帧图像的跟踪结果：<br><img src="https://cdn.nlark.com/yuque/0/2021/png/448115/1617378449987-8566d6e0-96f1-40c4-9ec0-e5bebea8a60d.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_22%2Ctext_6YKj5bCR5bm05ZKM54uX44CB8J-Nig%3D%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10" srcset="/img/loading.gif" lazyload alt="image.png"></p>
<h4 id="10-2-2-Camshift"><a href="#10-2-2-Camshift" class="headerlink" title="10.2.2 Camshift"></a>10.2.2 Camshift</h4><p>大家认真看下上面的结果，有一个问题，就是检测的窗口的大小是固定的，而狗狗由近及远是一个逐渐变小的过程，固定的窗口是不合适的。所以我们需要根据目标的大小和角度来对窗口的大小和角度进行修正。CamShift 可以帮我们解决这个问题。<br>CamShift 算法全称是“Continuously Adaptive Mean-Shift”（连续自适应 MeanShift 算法），是对 MeanShift 算法的改进算法，可随着跟踪目标的大小变化实时调整搜索窗口的大小，具有较好的跟踪效果。<br>Camshift 算法首先应用 meanshift，一旦 meanshift 收敛，它就会更新窗口的大小，还计算最佳拟合椭圆的方向，从而根据目标的位置和大小更新搜索窗口。如下图所示：<br><img src="https://cdn.nlark.com/yuque/0/2021/gif/448115/1617378432441-480ada39-1949-42f4-abf3-6fc6561f96b5.gif#height=510&amp;id=okHSy&amp;margin=%5Bobject%20Object%5D&amp;name=image4.gif&amp;originHeight=510&amp;originWidth=340&amp;originalType=binary∶=1&amp;size=253144&amp;status=done&amp;style=none&amp;width=340" srcset="/img/loading.gif" lazyload alt="image4.gif"><br>Camshift 在 OpenCV 中实现时，只需将上述的 meanshift 函数改为 Camshift 函数即可：<br>将 Camshift 中的：</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token comment"># 4.4 进行meanshift追踪</span>
        ret<span class="token punctuation">,</span> track_window <span class="token operator">=</span> cv<span class="token punctuation">.</span>meanShift<span class="token punctuation">(</span>dst<span class="token punctuation">,</span> track_window<span class="token punctuation">,</span> term_crit<span class="token punctuation">)</span>
        <span class="token comment"># 4.5 将追踪的位置绘制在视频上，并进行显示</span>
        x<span class="token punctuation">,</span>y<span class="token punctuation">,</span>w<span class="token punctuation">,</span>h <span class="token operator">=</span> track_window
        img2 <span class="token operator">=</span> cv<span class="token punctuation">.</span>rectangle<span class="token punctuation">(</span>frame<span class="token punctuation">,</span> <span class="token punctuation">(</span>x<span class="token punctuation">,</span>y<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">(</span>x<span class="token operator">+</span>w<span class="token punctuation">,</span>y<span class="token operator">+</span>h<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token number">255</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<p>改为：</p>
<div class="code-wrapper"><pre class="line-numbers language-python" data-language="python"><code class="language-python"><span class="token comment">#进行camshift追踪</span>
    ret<span class="token punctuation">,</span> track_window <span class="token operator">=</span> cv<span class="token punctuation">.</span>CamShift<span class="token punctuation">(</span>dst<span class="token punctuation">,</span> track_window<span class="token punctuation">,</span> term_crit<span class="token punctuation">)</span>
        <span class="token comment"># 绘制追踪结果</span>
        pts <span class="token operator">=</span> cv<span class="token punctuation">.</span>boxPoints<span class="token punctuation">(</span>ret<span class="token punctuation">)</span>
        pts <span class="token operator">=</span> np<span class="token punctuation">.</span>int0<span class="token punctuation">(</span>pts<span class="token punctuation">)</span>
        img2 <span class="token operator">=</span> cv<span class="token punctuation">.</span>polylines<span class="token punctuation">(</span>frame<span class="token punctuation">,</span><span class="token punctuation">[</span>pts<span class="token punctuation">]</span><span class="token punctuation">,</span><span class="token boolean">True</span><span class="token punctuation">,</span> <span class="token number">255</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div>
<h4 id="10-2-3-算法总结"><a href="#10-2-3-算法总结" class="headerlink" title="10.2.3 算法总结"></a>10.2.3 算法总结</h4><p>Meanshift 和 camshift 算法都各有优势，自然也有劣势：</p>
<ul>
<li>Meanshift 算法：简单，迭代次数少，但无法解决目标的遮挡问题并且不能适应运动目标的的形状和大小变化。</li>
<li><p>camshift 算法：可适应运动目标的大小形状的改变，具有较好的跟踪效果，但当背景色和目标颜色接近时，容易使目标的区域变大，最终有可能导致目标跟踪丢失。</p>
</li>
<li><p>官方文档：<a target="_blank" rel="noopener" href="https://docs.opencv.org/3.0-beta/modules/imgproc/doc/miscellaneous_transformations.html?highlight=adaptivethreshold#cv2.adaptiveThreshold">https://docs.opencv.org/3.0-beta/modules/imgproc/doc/miscellaneous_transformations.html?highlight=adaptivethreshold#cv2.adaptiveThreshold</a></p>
</li>
<li>Tutorial：<a target="_blank" rel="noopener" href="https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_gui/py_trackbar/py_trackbar.html#trackbar">https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_gui/py_trackbar/py_trackbar.html#trackbar</a></li>
</ul>

            </div>
            <hr>
            <div>
              <div class="post-metas mb-3">
                
                
              </div>
              
                <p class="note note-warning">
                  
                    本博客所有文章除特别声明外，均采用 <a target="_blank" href="https://creativecommons.org/licenses/by-sa/4.0/deed.zh" rel="nofollow noopener noopener">CC BY-SA 4.0 协议</a> ，转载请注明出处！
                  
                </p>
              
              
                <div class="post-prevnext">
                  <article class="post-prev col-6">
                    
                    
                      <a href="/yuque/Zotero%E9%85%8D%E7%BD%AE%E6%8C%87%E5%8D%97/">
                        <i class="iconfont icon-arrowleft"></i>
                        <span class="hidden-mobile">Zotero配置指南</span>
                        <span class="visible-mobile">上一篇</span>
                      </a>
                    
                  </article>
                  <article class="post-next col-6">
                    
                    
                      <a href="/AliyunDriver-to-Windows/">
                        <span class="hidden-mobile">AliyunDriver_to_Windows</span>
                        <span class="visible-mobile">下一篇</span>
                        <i class="iconfont icon-arrowright"></i>
                      </a>
                    
                  </article>
                </div>
              
            </div>

            
              <!-- Comments -->
              <article class="comments" id="comments" lazyload>
                
                  
                
                
  <div id="valine"></div>
  <script type="text/javascript">
    Fluid.utils.loadComments('#valine', function() {
      Fluid.utils.createScript('https://cdn.jsdelivr.net/npm/valine@1/dist/Valine.min.js', function() {
        var options = Object.assign(
          {"appId":"w8VaEP3iTgYj1EnQ7TsHSp6k-gzGzoHsz","appKey":"bB6pIAfcqCjPz7ujeqh5nVut","path":"window.location.pathname","placeholder":"说点什么","avatar":"retro","meta":["nick","mail","link"],"requiredFields":[],"pageSize":10,"lang":"zh-CN","highlight":false,"recordIP":false,"serverURLs":"","emojiCDN":null,"emojiMaps":null,"enableQQ":false},
          {
            el: "#valine",
            path: window.location.pathname
          }
        )
        new Valine(options);
        Fluid.utils.waitElementVisible('#valine .vcontent', () => {
          Fluid.plugins.initFancyBox('#valine .vcontent img:not(.vemoji)');
        })
      });
    });
  </script>
  <noscript>Please enable JavaScript to view the comments</noscript>


              </article>
            
          </article>
        </div>
      </div>
    </div>
    
      <div class="d-none d-lg-block col-lg-2 toc-container" id="toc-ctn">
        <div id="toc">
  <p class="toc-header"><i class="iconfont icon-list"></i>&nbsp;目录</p>
  <div class="toc-body" id="toc-body"></div>
</div>

      </div>
    
  </div>
</div>

<!-- Custom -->


    

    
      <a id="scroll-top-button" aria-label="TOP" href="#" role="button">
        <i class="iconfont icon-arrowup" aria-hidden="true"></i>
      </a>
    

    
      <div class="modal fade" id="modalSearch" tabindex="-1" role="dialog" aria-labelledby="ModalLabel"
     aria-hidden="true">
  <div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
    <div class="modal-content">
      <div class="modal-header text-center">
        <h4 class="modal-title w-100 font-weight-bold">搜索</h4>
        <button type="button" id="local-search-close" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body mx-3">
        <div class="md-form mb-5">
          <input type="text" id="local-search-input" class="form-control validate">
          <label data-error="x" data-success="v"
                 for="local-search-input">关键词</label>
        </div>
        <div class="list-group" id="local-search-result"></div>
      </div>
    </div>
  </div>
</div>
    

    
  </main>

  <footer class="text-center mt-5 py-3">
  <div class="footer-content">
     <a href="https://hexo.io" target="_blank" rel="nofollow noopener"><span>Hexo</span></a> <i class="iconfont icon-love"></i> <a href="https://github.com/fluid-dev/hexo-theme-fluid" target="_blank" rel="nofollow noopener"><span>Fluid</span></a> <font size="3" face="" color="#2f4154"> <p class="copyright text-muted"> Copyright © Veen 2021 <br> Find me on <a href="https://github.com/Veenxz" target="_blank">GitHub</a> | <a href="https://creativecommons.org/licenses/by-sa/4.0/deed.zh" target="_blank"> <img src="https://d33wubrfki0l68.cloudfront.net/3031be41e8753c70508aa88e84ed8f4f653f157e/d2d9a/images/cc-by-nc-sa.svg" srcset="/img/loading.gif" lazyload alt="Creative Commons"> </a> </p> </font> <div> <span id="timeDate">载入天数...</span> <span id="times">载入时分秒...</span> <script src="/js/duration.js"></script> </div> 
  </div>
  
  <div class="statistics">
    
    

    
      
        <!-- 不蒜子统计PV -->
        <span id="busuanzi_container_site_pv" style="display: none">
            总访问量 
            <span id="busuanzi_value_site_pv"></span>
             次
          </span>
      
      
        <!-- 不蒜子统计UV -->
        <span id="busuanzi_container_site_uv" style="display: none">
            总访客数 
            <span id="busuanzi_value_site_uv"></span>
             人
          </span>
      
    
  </div>


  

  
</footer>


  <!-- SCRIPTS -->
  
  <script  src="https://cdn.jsdelivr.net/npm/nprogress@0/nprogress.min.js" ></script>
  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/nprogress@0/nprogress.min.css" />

  <script>
    NProgress.configure({"showSpinner":false,"trickleSpeed":100})
    NProgress.start()
    window.addEventListener('load', function() {
      NProgress.done();
    })
  </script>


<script  src="https://cdn.jsdelivr.net/npm/jquery@3/dist/jquery.min.js" ></script>
<script  src="https://cdn.jsdelivr.net/npm/bootstrap@4/dist/js/bootstrap.min.js" ></script>
<script  src="/js/events.js" ></script>
<script  src="/js/plugins.js" ></script>

<!-- Plugins -->


  <script  src="/js/local-search.js" ></script>



  
    <script  src="/js/img-lazyload.js" ></script>
  



  
    
  



  
    <script  src="https://cdn.jsdelivr.net/npm/tocbot@4/dist/tocbot.min.js" ></script>
  
  
    <script  src="https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3/dist/jquery.fancybox.min.js" ></script>
  
  
    <script  src="https://cdn.jsdelivr.net/npm/anchor-js@4/anchor.min.js" ></script>
  
  
    <script defer src="https://cdn.jsdelivr.net/npm/clipboard@2/dist/clipboard.min.js" ></script>
  



  <script defer src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js" ></script>




  <script  src="https://cdn.jsdelivr.net/npm/typed.js@2/lib/typed.min.js" ></script>
  <script>
    (function (window, document) {
      var typing = Fluid.plugins.typing;
      var title = document.getElementById('subtitle').title;
      
      typing(title)
      
    })(window, document);
  </script>





  

  
    <!-- MathJax -->
    <script>
      MathJax = {
        tex: {
          inlineMath: [['$', '$'], ['\\(', '\\)']]
        },
        loader: {
          load: ['ui/lazy']
        },
        options: {
          renderActions: {
            findScript: [10, doc => {
              document.querySelectorAll('script[type^="math/tex"]').forEach(node => {
                const display = !!node.type.match(/; *mode=display/);
                const math = new doc.options.MathItem(node.textContent, doc.inputJax[0], display);
                const text = document.createTextNode('');
                node.parentNode.replaceChild(text, node);
                math.start = { node: text, delim: '', n: 0 };
                math.end = { node: text, delim: '', n: 0 };
                doc.math.push(math);
              });
            }, '', false],
            insertedScript: [200, () => {
              document.querySelectorAll('mjx-container').forEach(node => {
                let target = node.parentNode;
                if (target.nodeName.toLowerCase() === 'li') {
                  target.parentNode.classList.add('has-jax');
                }
              });
            }, '', false]
          }
        }
      };
    </script>

    <script async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js" ></script>

  











<!-- 主题的启动项 保持在最底部 -->
<script  src="/js/boot.js" ></script>


</body>
</html>
